summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiam Hopkins <liamh@google.com>2019-09-05 13:00:12 -0700
committerLiam Hopkins <liamh@google.com>2019-09-05 13:00:12 -0700
commit554deaf6a44977e7be6d357b472cb6c7639ce9ab (patch)
treeff3eadbb7ce61597996054e507e7431453fed45d
parent688bcbd32ef2c8cd014def57413ba76cf2ee7257 (diff)
parentc3f01c2d586dd01920aff180f0152df9af34ed08 (diff)
downloadgoogle-compute-image-packages-554deaf6a44977e7be6d357b472cb6c7639ce9ab.tar.gz
Merge branch 'development'
-rwxr-xr-xdaisy_workflows/build_deb_packages.sh1
-rwxr-xr-xdaisy_workflows/build_el_packages.sh1
-rw-r--r--packages/google-compute-engine-oslogin/Makefile19
-rw-r--r--packages/google-compute-engine-oslogin/README.md222
-rw-r--r--packages/google-compute-engine-oslogin/google_oslogin_control461
-rw-r--r--packages/google-compute-engine-oslogin/man/nss-cache-oslogin.848
-rw-r--r--packages/google-compute-engine-oslogin/man/nss-oslogin.841
-rw-r--r--packages/google-compute-engine-oslogin/packaging/debian/changelog164
-rw-r--r--packages/google-compute-engine-oslogin/packaging/debian/compat1
-rw-r--r--packages/google-compute-engine-oslogin/packaging/debian/control13
-rw-r--r--packages/google-compute-engine-oslogin/packaging/debian/copyright27
-rwxr-xr-xpackages/google-compute-engine-oslogin/packaging/debian/rules6
-rw-r--r--packages/google-compute-engine-oslogin/packaging/debian/source/format1
-rw-r--r--packages/google-compute-engine-oslogin/packaging/google-compute-engine-oslogin.spec101
-rwxr-xr-xpackages/google-compute-engine-oslogin/packaging/setup_deb.sh54
-rwxr-xr-xpackages/google-compute-engine-oslogin/packaging/setup_rpm.sh43
-rw-r--r--packages/google-compute-engine-oslogin/selinux/Makefile17
-rw-r--r--packages/google-compute-engine-oslogin/selinux/README.md17
-rw-r--r--packages/google-compute-engine-oslogin/selinux/oslogin.fc2
-rw-r--r--packages/google-compute-engine-oslogin/selinux/oslogin.ppbin1798 -> 0 bytes
-rw-r--r--packages/google-compute-engine-oslogin/selinux/oslogin.te24
-rw-r--r--packages/google-compute-engine-oslogin/src/Makefile86
-rw-r--r--packages/google-compute-engine-oslogin/src/authorized_keys/authorized_keys.cc78
-rw-r--r--packages/google-compute-engine-oslogin/src/cache_refresh/cache_refresh.cc119
-rw-r--r--packages/google-compute-engine-oslogin/src/include/compat.h62
-rw-r--r--packages/google-compute-engine-oslogin/src/include/nss_cache_oslogin.h65
-rw-r--r--packages/google-compute-engine-oslogin/src/include/oslogin_utils.h238
-rw-r--r--packages/google-compute-engine-oslogin/src/nss/compat/getpwent_r.c87
-rw-r--r--packages/google-compute-engine-oslogin/src/nss/nss_cache_oslogin.c274
-rw-r--r--packages/google-compute-engine-oslogin/src/nss/nss_oslogin.cc209
-rw-r--r--packages/google-compute-engine-oslogin/src/pam/pam_oslogin_admin.cc100
-rw-r--r--packages/google-compute-engine-oslogin/src/pam/pam_oslogin_login.cc273
-rw-r--r--packages/google-compute-engine-oslogin/src/utils.cc864
-rw-r--r--packages/google-compute-engine-oslogin/test/Makefile34
-rw-r--r--packages/google-compute-engine-oslogin/test/oslogin_utils_test.cc627
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/boto/boto_config.py13
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/boto/tests/boto_config_test.py4
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/compat.py4
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/__init__.py0
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/tests/__init__.py0
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/tests/utils_test.py80
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/utils.py71
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_9/utils.py8
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/el_6/utils.py14
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/el_7/utils.py8
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/freebsd_11/utils.py8
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/helpers.py15
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/sles_11/__init__.py0
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/sles_11/tests/__init__.py0
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/sles_11/tests/utils_test.py91
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/sles_11/utils.py88
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/sles_12/utils.py8
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/networking/network_daemon.py17
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/networking/tests/network_daemon_test.py30
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/tests/compat_test.py4
-rw-r--r--packages/python-google-compute-engine/packaging/debian/changelog8
-rwxr-xr-xpackages/python-google-compute-engine/packaging/setup_deb.sh2
-rwxr-xr-xpackages/python-google-compute-engine/packaging/setup_rpm.sh2
-rwxr-xr-xpackages/python-google-compute-engine/setup.py2
59 files changed, 117 insertions, 4739 deletions
diff --git a/daisy_workflows/build_deb_packages.sh b/daisy_workflows/build_deb_packages.sh
index d877064..061b31d 100755
--- a/daisy_workflows/build_deb_packages.sh
+++ b/daisy_workflows/build_deb_packages.sh
@@ -43,6 +43,7 @@ fi
# Build packages.
cd compute-image-packages/packages
for package in *; do
+ [[ -d "${package}/packaging" ]] || continue
pushd "$package"
./packaging/setup_deb.sh
if [[ $? -ne 0 ]]; then
diff --git a/daisy_workflows/build_el_packages.sh b/daisy_workflows/build_el_packages.sh
index d02f1ed..264f795 100755
--- a/daisy_workflows/build_el_packages.sh
+++ b/daisy_workflows/build_el_packages.sh
@@ -43,6 +43,7 @@ fi
# Build packages.
cd compute-image-packages/packages
for package in *; do
+ [[ -d "${package}/packaging" ]] || continue
pushd "$package"
./packaging/setup_rpm.sh
if [[ $? -ne 0 ]]; then
diff --git a/packages/google-compute-engine-oslogin/Makefile b/packages/google-compute-engine-oslogin/Makefile
deleted file mode 100644
index b22c16f..0000000
--- a/packages/google-compute-engine-oslogin/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-all install :
- $(MAKE) -C src $@
-
-tests :
- $(MAKE) -C test $@
-
-clean :
- $(MAKE) -C src clean
- $(MAKE) -C test clean
-
-prowbuild : debian_deps all
-
-prowtest : debian_deps tests
-
-debian_deps :
- sudo apt-get -y install g++ libcurl4-openssl-dev libjson-c-dev libpam-dev \
- googletest && touch $@
-
-.PHONY : all clean install prowbuild prowtest
diff --git a/packages/google-compute-engine-oslogin/README.md b/packages/google-compute-engine-oslogin/README.md
index 4acc31e..0eb1804 100644
--- a/packages/google-compute-engine-oslogin/README.md
+++ b/packages/google-compute-engine-oslogin/README.md
@@ -1,222 +1,4 @@
## OS Login Guest Environment for Google Compute Engine
-This repository contains the system components responsible for providing Google
-Cloud OS Login features on Google Compute Engine instances.
-
-**Table of Contents**
-
-* [Overview](#overview)
-* [Components](#components)
- * [Authorized Keys Command](#authorized-keys-command)
- * [NSS Modules](#nss-modules)
- * [PAM Modules](#pam-modules)
-* [Utilities](#Utilities)
- * [Control Script](#control-script)
- * [SELinux Policy](#selinux-policy)
-* [Source Packages](#source-packages)
- * [DEB](#deb)
- * [RPM](#rpm)
-
-## Overview
-
-The OS Login Guest Environment consists of the following main components:
-
-* **Authorized Keys Command** which provides SSH keys from the user's OS Login
- profile to sshd for authenticating users at login.
-* **NSS Modules** which provide support for making OS Login user and group
- information available to the system, using NSS (Name Service Switch)
- functionality.
-* **PAM Modules** which provide authorization (and authentication if
- two-factor support is enabled) support allowing the system to use Google
- Cloud IAM permissions to control the ability to log into an instance or to
- perform operations as root (via `sudo`).
-
-In addition to the main components, there are also the following utilities:
-
-* **google_oslogin_control** is a shell script for activating/deactivating the
- OS Login components.
-* **google_oslogin_nss_cache** is a utility for updating the local user and
- group cache.
-* **selinux** contains SELinux policy definition files and a compiled policy
- package for configuring SELinux to support OS Login.
-
-The **packaging** directory also contains files used to generate `.deb` and
-`.rpm` packages for the OS Login components.
-
-## Components
-
-#### Authorized Keys Command
-
-The `google_authorized_keys` binary is designed to be used with the sshd
-`AuthorizedKeysCommand` option in [sshd_config(5)](https://linux.die.net/man/5/sshd_config).
-It does the following:
-
-* Reads the user's profile information from the metadata server:
- ```
- http://metadata.google.internal/computeMetadata/v1/oslogin/users?username=<username>
- ```
-* Checks to make sure that the user is authorized to log in:
- ```
- http://metadata.google.internal/computeMetadata/v1/oslogin/authorize?email=<user_email>&policy=login
- ```
-* If the check is successful, returns the SSH keys associated with the user
- for use by sshd. Otherwise, exits with an error code.
-
-#### NSS Modules
-
-`libnss_oslogin.so` and `libnss_cache_oslogin.so` are NSS service modules which
-make OS Login users and groups available for use on the local system. The module
-is activated by adding `oslogin` and `cache_oslogin` entries for services in
-[nsswitch.conf(5)](https://linux.die.net/man/5/nsswitch.conf).
-
-* To return a list of all users, the NSS module queries:
- ```
- http://metadata.google.internal/computeMetadata/v1/oslogin/users?pagesize=<pagesize>
- ```
-* To look up a user by username, the NSS module queries:
- ```
- http://metadata.google.internal/computeMetadata/v1/oslogin/users?username=<username>
- ```
-* To look up a user by UID, the NSS module queries:
- ```
- http://metadata.google.internal/computeMetadata/v1/oslogin/users?uid=<uid>
- ```
-
-#### PAM Modules
-
-`pam_oslogin_login.so` is a PAM module which determines whether a given user is
-allowed to SSH into an instance.
-
-It is activated by adding an entry for the account group to the PAM service
-config for sshd as:
- ```
- account requisite pam_oslogin_login.so
- ```
-
-This module:
-
-* Retrieves the user's profile information from the metadata server:
- ```
- http://metadata.google.internal/computeMetadata/v1/oslogin/users?username=<username>
- ```
-* If the user does not have OS Login profile information it is passed on to
- the system authentication modules to be processed as a local user.
-* Otherwise, the module confirms whether the user has permissions to SSH into
- the instance:
- ```
- http://metadata.google.internal/computeMetadata/v1/oslogin/authorize?email=<user_email>&policy=login
- ```
-* If the user is authorized, PAM returns a success message and SSH can
- proceed. Otherwise, PAM returns a denied message and the SSH check will
- fail.
-
-`pam_oslogin_admin.so` is a PAM module which determines whether a given user
-should have admin (sudo) permissions on the instance.
-
-It is activated by adding an entry for the `account` group to the PAM service
-config for sshd config as:
- ```
- account optional pam_oslogin_admin.so
- ```
-
-This module:
-
-* Retrieves the user's profile information from the metadata server.
- ```
- http://metadata.google.internal/computeMetadata/v1/oslogin/users?username=<username>
- ```
-* If the user is not an OS Login user (a local user account), the module
- returns success.
-* Otherwise, the module determines if the user has admin permissions:
- ```
- http://metadata.google.internal/computeMetadata/v1/oslogin/authorize?email=<user_email>&policy=adminLogin
- ```
-* If the user is authorized as an admin, a file with the username is added to
- `/var/google-sudoers.d/`. The file gives the user sudo privileges.
-* If the authorization check fails for admin permissions, the file is removed
- from `/var/google-sudoers.d/` if it exists.
-
-## Utilities
-
-#### Control Script
-
-The `google_oslogin_control` shell script activates or deactivates the OS Login
-features. It is invoked by the google accounts daemon. The control file performs
-the following tasks:
-
-* Adds (or removes) AuthorizedKeysCommand and AuthorizedKeysCommandUser lines
- to (from) `sshd_config` and restarts sshd.
-* Adds (or removes) `oslogin` and `cache_oslogin` to (from) `nsswitch.conf`.
-* Adds (or removes) the `account` entries to (from) the PAM sshd config. Also
- adds (or removes) the `pam_mkhomedir.so` module to automatically create the
- home directory for an OS Login user.
-* Creates (or deletes) the `/var/google-sudoers.d/` directory, and a file
- called `google-oslogin` in `/etc/sudoers.d/` that includes the directory.
-
-#### SELinux Policy
-
-The `selinux` directory contains `.te` (type enforcement) and `.fc` (file
-context) files used by SELinux to give the OS Login features the appropriate
-SELinux permissions. These are compiled using `checkmodule` and
-`semodule_package` to create an policy package `oslogin.pp`.
-
-## Source Packages
-
-There is currently support for creating packages for the following distros:
-
-* Debian 9
-* CentOS/RHEL 6
-* CentOS/RHEL 7
-
-Files for these packages are in the `packaging/` directory.
-
-#### DEB
-
-_Note: the `packaging/setup_deb.sh` script performs these steps, but is not
-production quality._
-
-1. Install build dependencies:
- ```
- sudo apt-get -y install make g++ libcurl4-openssl-dev libjson-c-dev libpam-dev
- ```
-1. Install deb creation tools:
- ```
- sudo apt-get -y install debhelper devscripts build-essential
- ```
-1. Create a compressed tar file named
- `google-compute-engine-oslogin_M.M.R.orig.tar.gz` using the files in this
- directory, excluding the `packaging` directory (where M.M.R is the version
- number).
-1. In a separate directory, extract the `.orig.tar.gz` file and copy the
- `debian` directory into the top level.
-1. To build the package, run the command
- ```
- debuild -us -uc
- ```
-
-#### RPM
-
-_Note: the `packaging/setup_rpm.sh` script performs these steps, but is not
-production quality._
-
-1. Install build dependencies:
- ```
- sudo yum -y install make gcc-c++ libcurl-devel json-c json-c-devel pam-devel policycoreutils-python
- ```
-1. Install rpm creation tools:
- ```
- sudo yum -y install rpmdevtools
- ```
-1. Create a compressed tar file named
- `google-compute-engine-oslogin_M.M.R.orig.tar.gz` using the files in this
- directory, excluding the `packaging` directory (where M.M.R is the version
- number).
-1. In a separate location, create a directory called `rpmbuild` and a
- subdirectory called `SOURCES`. Copy the `.orig.tar.gz` file into the
- `SOURCES` directory.
-1. Copy the `SPECS` directory from the `rpmbuild` directory here into the
- `rpmbuild` directory you created.
-1. To build the package, run the command:
- ```
- rpmbuild --define "_topdir /path/to/rpmbuild" -ba /path/to/rpmbuild/SPECS/google-compute-engine-oslogin.spec
- ```
+**This package has moved. The OS Login on-guest components are now located in
+the [guest-oslogin](https://github.com/GoogleCloudPlatform/guest-oslogin) repo**
diff --git a/packages/google-compute-engine-oslogin/google_oslogin_control b/packages/google-compute-engine-oslogin/google_oslogin_control
deleted file mode 100644
index bc85a8e..0000000
--- a/packages/google-compute-engine-oslogin/google_oslogin_control
+++ /dev/null
@@ -1,461 +0,0 @@
-#!/bin/sh
-# Copyright 2017 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-is_freebsd() {
- [ "$(uname)" = "FreeBSD" ]
- return $?
-}
-
-nss_config="/etc/nsswitch.conf"
-pam_sshd_config="/etc/pam.d/sshd"
-pam_su_config="/etc/pam.d/su"
-sshd_config="/etc/ssh/sshd_config"
-group_config="/etc/security/group.conf"
-sudoers_dir="/var/google-sudoers.d"
-users_dir="/var/google-users.d"
-added_comment="# Added by Google Compute Engine OS Login."
-sshd_block="#### Google OS Login control. Do not edit this section. ####"
-sshd_end_block="#### End Google OS Login control section. ####"
-sudoers_file="/etc/sudoers.d/google-oslogin"
-if is_freebsd; then
- sudoers_file="/usr/local/etc/sudoers.d/google-oslogin"
-fi
-
-# Update nsswitch.conf to include OS Login NSS module for passwd.
-modify_nsswitch_conf() {
- local nss_config="${1:-${nss_config}}"
-
- if ! grep -q '^passwd:.*oslogin' "$nss_config"; then
- $sed -i"" '/^passwd:/ s/$/ cache_oslogin oslogin/' "$nss_config"
- fi
-
- if is_freebsd && grep -q '^passwd:.*compat' "$nss_config"; then
- $sed -i"" '/^passwd:/ s/compat/files/' "$nss_config"
- fi
-}
-
-restore_nsswitch_conf() {
- local nss_config="${1:-${nss_config}}"
-
- $sed -i"" '/^passwd:/ s/ cache_oslogin oslogin//' "$nss_config"
- if is_freebsd; then
- $sed -i"" '/^passwd:/ s/files/compat/' "$nss_config"
- fi
-}
-
-modify_sshd_conf() (
- set -e
-
- local sshd_config="${1:-${sshd_config}}"
-
- local sshd_auth_keys_command="AuthorizedKeysCommand /usr/bin/google_authorized_keys"
- local sshd_auth_keys_command_user="AuthorizedKeysCommandUser root"
- local sshd_auth_methods="AuthenticationMethods publickey,keyboard-interactive"
- local sshd_challenge="ChallengeResponseAuthentication yes"
-
- # Update google_authorized_keys path in FreeBSD.
- if is_freebsd; then
- sshd_auth_keys_command="AuthorizedKeysCommand /usr/local/bin/google_authorized_keys"
- fi
-
- # Update directives for EL 6.
- if grep -qs "release 6" /etc/redhat-release; then
- sshd_auth_keys_command_user="AuthorizedKeysCommandRunAs root"
- sshd_auth_methods="RequiredAuthentications2 publickey,keyboard-interactive"
- fi
-
- add_or_update_sshd() {
- local entry="$1"
- local sshd_config="$2"
- local directive="$(echo "$entry" | cut -d' ' -f1)"
- local value="$(echo "$entry" | cut -d' ' -f2-)"
-
- # Check if directive is present.
- if grep -Eq "^\s*${directive}" "$sshd_config"; then
- # Check if value is incorrect.
- if ! grep -Eq "^\s*${directive}(\s|=)+${value}" "$sshd_config"; then
- # Comment out the line (because sshd_config is first-directive-found)
- # and add to end section.
- $sed -i"" -E "/^\s*${directive}/ s/^/${added_comment}\n#/" "$sshd_config"
- $sed -i"" "/$sshd_end_block/ i${entry}" "$sshd_config"
- fi
- else
- $sed -i"" "/$sshd_end_block/ i${entry}" "$sshd_config"
- fi
- }
-
- # Setup Google config block.
- if ! grep -q "$sshd_block" "$sshd_config"; then
- # Remove old-style additions.
- $sed -i"" "/${added_comment}/,+1d" "$sshd_config"
- printf "\n\n${sshd_block}\n${sshd_end_block}" >> "$sshd_config"
- fi
-
- for entry in "$sshd_auth_keys_command" "$sshd_auth_keys_command_user"; do
- add_or_update_sshd "$entry" "$sshd_config"
- done
-
- if [ -n "$two_factor" ]; then
- for entry in "$sshd_auth_methods" "$sshd_challenge"; do
- add_or_update_sshd "$entry" "$sshd_config"
- done
- fi
-)
-
-restore_sshd_conf() {
- local sshd_config="${1:-${sshd_config}}"
-
- if ! grep -q "$sshd_block" "$sshd_config"; then
- # Remove old-style additions.
- $sed -i"" "/${added_comment}/,+1d" "$sshd_config"
- else
- # Uncomment commented-out fields and remove Google config block.
- $sed -i"" "/${added_comment}/{n;s/^#//}" "$sshd_config"
- $sed -i"" "/${added_comment}/d" "$sshd_config"
- $sed -i"" "/${sshd_block}/,/${sshd_end_block}/d" "$sshd_config"
- fi
-}
-
-# Inserts pam modules to relevant pam stacks if missing.
-modify_pam_config() (
- # TODO: idempotency of this function would be better assured if it wiped out
- # and applied desired changes each time rather than detecting deltas.
-
- set -e
-
- local pam_sshd_config="${1:-${pam_sshd_config}}"
- local pam_su_config="${1:-${pam_su_config}}"
-
- local pam_auth_oslogin="auth [success=done perm_denied=die default=ignore] pam_oslogin_login.so"
- local pam_auth_group="auth [default=ignore] pam_group.so"
- local pam_account_oslogin="account [success=ok default=ignore] pam_oslogin_admin.so"
- local pam_account_admin="account [success=ok ignore=ignore default=die] pam_oslogin_login.so"
- local pam_session_homedir="session [success=ok default=ignore] pam_mkhomedir.so"
- local pam_account_su="account [success=bad ignore=ignore] pam_oslogin_login.so"
-
- # In FreeBSD, the used flags are not supported, replacing them with the
- # previous ones (requisite and optional). This is not an exact feature parity
- # with Linux.
- if is_freebsd; then
- pam_auth_oslogin="auth optional pam_oslogin_login.so"
- pam_auth_group="auth optional pam_group.so"
- pam_account_oslogin="account optional pam_oslogin_admin.so"
- pam_account_admin="account requisite pam_oslogin_login.so"
- pam_session_homedir="session optional pam_mkhomedir.so"
- fi
-
- local added_config=""
- local added_su_config=""
-
- # For COS this file is solely includes, so simply prepend the new config,
- # making each entry the top of its stack.
- if [ -e /etc/os-release ] && grep -q "ID=cos" /etc/os-release; then
- added_config="${added_comment}\n"
- for cfg in "$pam_account_admin" "$pam_account_oslogin" \
- "$pam_session_homedir" "$pam_auth_group"; do
- grep -qE "^${cfg%% *}.*${cfg##* }" ${pam_sshd_config} || added_config="${added_config}${cfg}\n"
- done
-
- if [ -n "$two_factor" ]; then
- grep -q "$pam_auth_oslogin" "$pam_sshd_config" || added_config="${added_config}${pam_auth_oslogin}\n"
- fi
-
- $sed -i"" "1i ${added_config}\n\n" "$pam_sshd_config"
-
- added_su_config="${added_comment}\n${pam_account_su}"
- $sed -i"" "1i ${added_su_config}" "$pam_su_config"
-
- return 0
- fi
-
- # Find the distro-specific insertion point for auth and su.
- if [ -e /etc/debian_version ]; then
- # Get location of common-auth and check if preceding line is a comment.
- insert=$($sed -rn "/^@include\s+common-auth/=" "$pam_sshd_config")
- $sed -n "$((insert-1))p" "$pam_sshd_config" | grep -q '^#' && insert=$((insert-1))
- su_insert=$($sed -rn "/^@include\s+common-account/=" "$pam_su_config")
- elif [ -e /etc/redhat-release ]; then
- # Get location of password-auth.
- insert=$($sed -rn "/^auth\s+(substack|include)\s+password-auth/=" \
- "$pam_sshd_config")
- # Get location of system-auth.
- su_insert=$($sed -rn "/^account\s+include\s+system-auth/=" "$pam_su_config")
- elif [ -e /etc/os-release ] && grep -q 'ID="sles"' /etc/os-release; then
- # Get location of common-auth.
- insert=$($sed -rn "/^auth\s+include\s+common-auth/=" "$pam_sshd_config")
- # Get location of common-account.
- su_insert=$($sed -rn "/^account\s+include\s+common-account/=" "$pam_su_config")
- elif [ -e /etc/arch-release ]; then
- # Get location of system-remote-login.
- insert=$($sed -rn "/^auth\s+include\s+system-remote-login/=" "$pam_sshd_config")
- # TODO: find su_insert point for arch linux.
- elif is_freebsd; then
- # Get location of the first auth occurrence
- insert=$($sed -rn '/^auth/=' "$pam_sshd_config" | head -1)
- fi
-
- added_config="$added_comment"
- if ! grep -qE '^auth.*pam_group' "$pam_sshd_config"; then
- added_config="${added_config}\n${pam_auth_group}"
- fi
-
- # This auth entry for OS Login+two factor MUST be added last, as it will
- # short-circuit processing of the auth stack via [success=ok]. auth stack
- # entries after this one will not be processed.
- if [ -n "$two_factor" ] && ! grep -qE '^auth.*oslogin' "$pam_sshd_config"; then
- added_config="${added_config}\n${pam_auth_oslogin}"
- fi
-
- # Insert auth modules at top of `sshd:auth` stack.
- if [ -n "$insert" ] && [ "$added_config" != "$added_comment" ]; then
- $sed -i"" "${insert}i ${added_config}" "$pam_sshd_config"
- fi
-
- # Insert su blocker at top of `su:account` stack.
- if [ -n "$su_insert" ] && ! grep -qE "$pam_account_su" "$pam_su_config"; then
- added_su_config="${added_comment}\n${pam_account_su}"
- $sed -i"" "${su_insert}i ${added_su_config}" "$pam_su_config"
- fi
-
- # Append account modules at end of `sshd:account` stack.
- if ! grep -qE '^account.*oslogin' "$pam_sshd_config"; then
- added_config="\\\n${added_comment}\n${pam_account_admin}\n${pam_account_oslogin}"
- account_end=$($sed -n '/^account/=' "$pam_sshd_config" | tail -1)
- $sed -i"" "${account_end}a ${added_config}" "$pam_sshd_config"
- fi
-
- # Append mkhomedir module at end of `sshd:session` stack.
- if ! grep -qE '^session.*mkhomedir' "$pam_sshd_config"; then
- added_config="\\\n${added_comment}\n${pam_session_homedir}"
- session_end=$($sed -n '/^session/=' "$pam_sshd_config" | tail -1)
- $sed -i"" "${session_end}a ${added_config}" "$pam_sshd_config"
- fi
-)
-
-restore_pam_config() {
- local pam_sshd_config="${1:-${pam_sshd_config}}"
- local pam_su_config="${1:-${pam_su_config}}"
-
- $sed -i"" "/${added_comment}/d" "$pam_sshd_config"
- $sed -i"" "/pam_oslogin/d" "$pam_sshd_config"
- $sed -i"" "/^session.*mkhomedir/d" "$pam_sshd_config"
- $sed -i"" "/^auth.*pam_group/d" "$pam_sshd_config"
-
- $sed -i"" "/${added_comment}/d" "$pam_su_config"
- $sed -i"" "/pam_oslogin/d" "$pam_su_config"
-}
-
-modify_group_conf() {
- # In FreeBSD there is no pam_group config file similar to
- # /etc/security/group.conf.
- if is_freebsd; then
- return
- fi
-
- local group_config="${1:-${group_config}}"
- local group_conf_entry="sshd;*;*;Al0000-2400;adm,dip,docker,lxd,plugdev,video"
-
- if ! grep -q "$group_conf_entry" "$group_config"; then
- $sed -i"" "\$a ${added_comment}\n${group_conf_entry}" "$group_config"
- fi
-}
-
-restore_group_conf() {
- # In FreeBSD there is no pam_group config file similar to
- # /etc/security/group.conf.
- if is_freebsd; then
- return
- fi
-
- local group_config="${1:-${group_config}}"
-
- $sed -i"" "/${added_comment}/{n;d}" "$group_config"
- $sed -i"" "/${added_comment}/d" "$group_config"
-}
-
-restart_service() {
- local service="$1"
-
- # The other options will be wrappers to systemctl on
- # systemd-enabled systems, so stop if found.
- if readlink -f /sbin/init|grep -q systemd; then
- if systemctl is-active --quiet "$service"; then
- systemctl restart "$service"
- return $?
- else
- return 0
- fi
- fi
-
- # Use the service helper if it exists.
- if command -v service > /dev/null; then
- if ! service "$service" status 2>&1 | grep -Eq "unrecognized|does not exist"; then
- service "$service" restart
- return $?
- else
- return 0
- fi
- fi
-
- # Fallback to trying sysvinit script of the same name.
- if command -v /etc/init.d/"$service" > /dev/null; then
- if /etc/init.d/"$service" status > /dev/null 2>&1; then
- /etc/init.d/"$service" restart
- return $?
- else
- return 0
- fi
- fi
-
- # We didn't find any way to restart this service.
- return 1
-}
-
-# Restart sshd unless --norestartsshd flag is set.
-restart_sshd() {
- if [ -n "$no_restart_sshd" ]; then
- return 0
- fi
- echo "Restarting SSHD"
- for svc in "ssh" "sshd"; do
- restart_service "$svc"
- done
-}
-
-restart_svcs() {
- echo "Restarting optional services."
- for svc in "nscd" "unscd" "systemd-logind" "cron" "crond"; do
- restart_service "$svc"
- done
-}
-
-setup_google_dirs() {
- for dir in "$sudoers_dir" "$users_dir"; do
- [ -d "$dir" ] && continue
- mkdir -p "$dir"
- chmod 750 "$dir"
- if fixfiles=$(command -v fixfiles); then
- $fixfiles restore "$dir"
- fi
- done
- echo "#includedir ${sudoers_dir}" > "$sudoers_file"
- chmod 0440 "$sudoers_file"
-}
-
-remove_google_dirs() {
- for dir in "$sudoers_dir" "$users_dir"; do
- rm -rf "$dir"
- done
- rm -f "$sudoers_file"
-}
-
-activate() {
- for func in modify_sshd_conf modify_nsswitch_conf \
- modify_pam_config setup_google_dirs restart_svcs restart_sshd \
- modify_group_conf; do
- $func
- [ $? -eq 0 ] || return 1
- done
-}
-
-deactivate() {
- for func in remove_google_dirs restore_nsswitch_conf \
- restore_sshd_conf restore_pam_config restart_svcs restart_sshd \
- restore_group_conf; do
- $func
- done
-}
-
-# get_status checks each file for appropriate updates and exits on first
-# failure. Checks for two factor config changes only if requested.
-get_status() (
- set -e
-
- grep -Eq '^account.*oslogin' "$pam_sshd_config"
- grep -Eq 'google_authorized_keys' "$sshd_config"
- grep -Eq 'passwd:.*oslogin' "$nss_config"
- if [ -n "$two_factor" ]; then
- grep -Eq '^auth.*oslogin' "$pam_sshd_config"
- grep -Eq '^(AuthenticationMethods|RequiredAuthentications2).*publickey,keyboard-interactive' "$sshd_config"
- fi
-)
-
-usage() {
- echo "Usage: $(basename "$0") {activate|deactivate|status} [--norestartsshd] [--twofactor]"
- echo "This script will activate or deactivate the features for"
- echo "Google Compute Engine OS Login and (optionally) two-factor authentication."
- echo "This script must be run as root."
- exit 1
-}
-
-
-# Main
-if [ $(id -u) -ne 0 ] || [ $# -lt 1 ]; then
- usage
-fi
-
-sed="sed"
-is_freebsd && sed="gsed"
-
-while [ $# -gt 0 ]; do
- case "$1" in
- --norestartsshd)
- no_restart_sshd="true"
- shift
- ;;
- --twofactor)
- two_factor="true"
- shift
- ;;
- activate)
- action="activate"
- shift
- ;;
- deactivate)
- action="deactivate"
- shift
- ;;
- status)
- action="status"
- shift
- ;;
- *)
- shift
- ;;
- esac
-done
-
-case "$action" in
- activate)
- echo "Activating Google Compute Engine OS Login."
- activate
- if [ $? -ne 0 ]; then
- echo "Failed to apply changes, rolling back"
- deactivate
- exit 1
- fi
- ;;
- deactivate)
- echo "Deactivating Google Compute Engine OS Login."
- deactivate
- ;;
- status)
- get_status
- exit $?
- ;;
- *)
- usage
- ;;
-esac
diff --git a/packages/google-compute-engine-oslogin/man/nss-cache-oslogin.8 b/packages/google-compute-engine-oslogin/man/nss-cache-oslogin.8
deleted file mode 100644
index aaf4f8e..0000000
--- a/packages/google-compute-engine-oslogin/man/nss-cache-oslogin.8
+++ /dev/null
@@ -1,48 +0,0 @@
-'\" t
-.TH "NSS\-CACHE\-OSLOGIN" "8" "2019-06-06" "Google Cloud"
-
-.\" IF GNU troff set Aq to sequence aq (Apostrophe quote)
-.ie \n(.g .ds Aq \(aq
-.\" ELSE set Aq to '
-.el .ds Aq '
-
-.\" disable hyphenation
-.nh
-.\" disable justification (adjust text to left margin only)
-.ad l
-
-.SH "NAME"
-nss-cache-oslogin, libnss_cache_oslogin.so.2 \- UNIX implementation for OS Login Users and Groups with local caching\&.
-
-.SH "SYNOPSIS"
-libnss_cache_oslogin\&.so\&.2
-
-.SH "DESCRIPTION"
-\fBnss\-cache\-oslogin\fR is a plug\-in module for the GNU Name Service Switch
-(NSS) functionality of the GNU C Library (\fBglibc\fR)\&.
-This module provides UNIX name resolution from a local cache of users and groups
-configured in the \fIGoogle Cloud OS Login\fR system\&.
-The "passwd" and "group" services are supported by this module\&.
-.PP
-To use the NSS module, add "cache_oslogin" to the appropriate service lines
-in nsswitch\&.conf\&.
-It is recommended to place "cache_oslogin" after any system provided modules
-and before the "oslogin" module, as it is a pass-through cache.
-
-.SH "FILES"
-.IP /etc/oslogin_passwd.cache
-user cache file
-.IP /etc/oslogin_group.cache
-group cache file
-
-.SH "NOTES"
-Documentation for the Google Cloud OS Login service is available online at
-.UR "https://cloud.google.com/compute/docs/oslogin"
-.UE
-
-.SH "SEE ALSO"
-.BR nss-oslogin (5),
-.BR nsswitch.conf (5),
-.BR nss (5),
-.BR getent (1),
-.BR initgroups (3)
diff --git a/packages/google-compute-engine-oslogin/man/nss-oslogin.8 b/packages/google-compute-engine-oslogin/man/nss-oslogin.8
deleted file mode 100644
index 3f4c763..0000000
--- a/packages/google-compute-engine-oslogin/man/nss-oslogin.8
+++ /dev/null
@@ -1,41 +0,0 @@
-'\" t
-.TH "NSS\-OSLOGIN" "8" "2019-06-06" "Google Cloud"
-
-.\" IF GNU troff set Aq to sequence aq (Apostrophe quote)
-.ie \n(.g .ds Aq \(aq
-.\" ELSE set Aq to '
-.el .ds Aq '
-
-.\" disable hyphenation
-.nh
-.\" disable justification (adjust text to left margin only)
-.ad l
-
-.SH "NAME"
-nss-oslogin, libnss_oslogin.so.2 \- UNIX implementation for OS Login Users and Groups\&.
-
-.SH "SYNOPSIS"
-libnss_oslogin\&.so\&.2
-
-.SH "DESCRIPTION"
-\fBnss\-oslogin\fR is a plug\-in module for the GNU Name Service Switch (NSS)
-functionality of the GNU C Library (\fBglibc\fR).
-This module provides UNIX name resolution for users and groups configured
-through the \fIGoogle Cloud OS Login\fR system\&.
-The "passwd", "group", and "initgroups" services are supported by this module.
-.PP
-To use the NSS module, add "oslogin" to the appropriate service lines
-in nsswitch\&.conf\&.
-It is recommended to place "oslogin" as the last entry for each service.
-
-.SH "NOTES"
-Documentation for the Google Cloud OS Login service is available online at
-.UR "https://cloud.google.com/compute/docs/oslogin"
-.UE
-
-.SH "SEE ALSO"
-.BR nss-cache-oslogin (8),
-.BR nsswitch.conf (5),
-.BR nss (5),
-.BR getent (1),
-.BR initgroups (3)
diff --git a/packages/google-compute-engine-oslogin/packaging/debian/changelog b/packages/google-compute-engine-oslogin/packaging/debian/changelog
deleted file mode 100644
index 5eb8a46..0000000
--- a/packages/google-compute-engine-oslogin/packaging/debian/changelog
+++ /dev/null
@@ -1,164 +0,0 @@
-google-compute-engine-oslogin (1:20190801.00-g1) stable; urgency=medium
-
- * Correct JSON refcount decrementing.
-
- -- Google Cloud Team <gc-team@google.com> Thu, 01 Aug 2019 13:57:16 -0700
-
-google-compute-engine-oslogin (1:20190729.00-g1) stable; urgency=medium
-
- * Remove unnecessary binary search logic.
-
- -- Google Cloud Team <gc-team@google.com> Mon, 29 Jul 2019 10:11:00 -0700
-
-google-compute-engine-oslogin (1:20190708.00-g1) stable; urgency=medium
-
- * Restructure Makefile and Debian control files.
- * Add man pages.
-
- -- Google Cloud Team <gc-team@google.com> Mon, 08 Jul 2019 10:20:01 -0700
-
-google-compute-engine-oslogin (1.5.3-1) unstable; urgency=low
-
- * Update OS Login control file for FreeBSD support.
-
- -- Google Cloud Team <gc-team@google.com> Wed, 22 May 2019 12:00:00 -0700
-
-google-compute-engine-oslogin (1.5.2-1) unstable; urgency=low
-
- * Fix pam_group ordering detection.
- * Restart cron on OS Login control.
- * Add PAM entry to su:account stack.
-
- -- Google Cloud Team <gc-team@google.com> Tue, 16 Apr 2019 12:00:00 -0700
-
-google-compute-engine-oslogin (1.5.1-1) unstable; urgency=low
-
- * Fix two factor auth action name.
-
- -- Google Cloud Team <gc-team@google.com> Tue, 13 Mar 2019 12:00:00 -0700
-
-google-compute-engine-oslogin (1.5.0-1) unstable; urgency=low
-
- * Support Google prompt for two factor authentication.
-
- -- Google Cloud Team <gc-team@google.com> Tue, 19 Feb 2019 12:00:00 -0700
-
-google-compute-engine-oslogin (1.4.3-1) unstable; urgency=low
-
- * Improve OS Login control file for BSD support.
- * Improve SELinux support.
-
- -- Google Cloud Team <gc-team@google.com> Wed, 05 Dec 2018 12:00:00 -0700
-
-google-compute-engine-oslogin (1.4.2-1+deb9) unstable; urgency=low
-
- * Improve OS Login control file.
- * Restart systemd-logind on OS Login enable.
-
- -- Google Cloud Team <gc-team@google.com> Tue, 04 Dec 2018 12:00:00 -0700
-
-google-compute-engine-oslogin (1.4.1-1+deb9) unstable; urgency=low
-
- * Improve SELinux support.
- * Improve OS Login control file.
-
- -- Google Cloud Team <gc-team@google.com> Fri, 30 Nov 2018 12:00:00 -0700
-
-google-compute-engine-oslogin (1.4.0-1+deb9) unstable; urgency=low
-
- * Support OS Login two factor authentication.
-
- -- Google Cloud Team <gc-team@google.com> Wed, 28 Nov 2018 12:00:00 -0700
-
-google-compute-engine-oslogin (1.3.1-1+deb9) unstable; urgency=low
-
- * Add user name validation to pam modules.
- * Return false on failed final load.
-
- -- Google Cloud Team <gc-team@google.com> Wed, 05 Sep 2018 12:00:00 -0700
-
-google-compute-engine-oslogin (1.3.0-1+deb9) unstable; urgency=low
-
- * Include libnss cache as part of the OS Login package.
-
- -- Google Cloud Team <gc-team@google.com> Tue, 01 May 2018 12:00:00 -0700
-
-google-compute-engine-oslogin (1.2.0-1+deb9) unstable; urgency=low
-
- * Add support for NSS cache.
-
- -- Google Cloud Team <gc-team@google.com> Thu, 08 Mar 2018 12:00:00 -0700
-
-google-compute-engine-oslogin (1.1.5-1+deb9) unstable; urgency=low
-
- * Clear the CURL_GLOBAL_SSL bit on curl initialization.
-
- -- Google Cloud Team <gc-team@google.com> Mon, 26 Feb 2018 12:00:00 -0700
-
-google-compute-engine-oslogin (1.1.4-1+deb9) unstable; urgency=low
-
- * Close socket connections when requesting metadata.
-
- -- Google Cloud Team <gc-team@google.com> Mon, 29 Jan 2018 12:00:00 -0700
-
-google-compute-engine-oslogin (1.1.3-1+deb9) unstable; urgency=low
-
- * Change the OS Login uid restriction to allow uid 1000.
-
- -- Google Cloud Team <gc-team@google.com> Thu, 25 Jan 2018 12:00:00 -0700
-
-google-compute-engine-oslogin (1.1.2-1+deb9) unstable; urgency=low
-
- * Fix parsing logic for expiration time on SSH public keys.
- * Fix home directory creation PAM config.
-
- -- MAINTAINER <gc-team@google.com> Wed, 29 Nov 2017 12:00:00 -0700
-
-google-compute-engine-oslogin (1.1.1-1+deb9) unstable; urgency=low
-
- * Remove logging when checking OS Login status.
-
- -- MAINTAINER <gc-team@google.com> Wed, 25 Oct 2017 12:00:00 -0700
-
-google-compute-engine-oslogin (1.1.0-1+deb9) unstable; urgency=low
-
- * OS Login is enabled via the google-compute-engine package.
-
- -- MAINTAINER <gc-team@google.com> Tue, 17 Oct 2017 12:00:00 -0700
-
-google-compute-engine-oslogin (1.0.5-1+deb9) unstable; urgency=low
-
- * JSON parser accepts string types for int64 values.
-
- -- MAINTAINER <gc-team@google.com> Fri, 06 Oct 2017 12:00:00 -0700
-
-google-compute-engine-oslogin (1.0.4-1+deb9) unstable; urgency=low
-
- * JSON parser casts uid and gid to unsigned integers.
-
- -- MAINTAINER <gc-team@google.com> Tue, 20 Sep 2017 12:00:00 -0700
-
-google-compute-engine-oslogin (1.0.3-1+deb9) unstable; urgency=low
-
- * Strictly check for HTTP code 200.
-
- -- MAINTAINER <gc-team@google.com> Tue, 25 Aug 2017 12:00:00 -0700
-
-google-compute-engine-oslogin (1.0.2-1+deb9) unstable; urgency=low
-
- * Improve security in case of transient errors.
-
- -- MAINTAINER <gc-team@google.com> Tue, 15 Aug 2017 12:00:00 -0700
-
-google-compute-engine-oslogin (1.0.1-1+deb9) unstable; urgency=low
-
- * Fix for restarting sshd and nscd.
-
- -- MAINTAINER <gc-team@google.com> Mon, 17 Jul 2017 12:00:00 -0700
-
-google-compute-engine-oslogin (1.0.0-1+deb9) unstable; urgency=low
-
- * Team Upload.
- * Initial release.
-
- -- MAINTAINER <gc-team@google.com> Thu, 22 Jun 2017 12:00:00 -0700
diff --git a/packages/google-compute-engine-oslogin/packaging/debian/compat b/packages/google-compute-engine-oslogin/packaging/debian/compat
deleted file mode 100644
index ec63514..0000000
--- a/packages/google-compute-engine-oslogin/packaging/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-9
diff --git a/packages/google-compute-engine-oslogin/packaging/debian/control b/packages/google-compute-engine-oslogin/packaging/debian/control
deleted file mode 100644
index ac14124..0000000
--- a/packages/google-compute-engine-oslogin/packaging/debian/control
+++ /dev/null
@@ -1,13 +0,0 @@
-Source: google-compute-engine-oslogin
-Maintainer: Google Cloud Team <gc-team@google.com>
-Section: misc
-Priority: optional
-Standards-Version: 3.9.8
-Build-Depends: debhelper (>= 9), libcurl4-openssl-dev, libjson-c-dev | libjson0-dev, libpam-dev
-
-Package: google-compute-engine-oslogin
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}
-Description: Google Compute Engine OS Login
- Contains libraries, applications and configurations for using OS Login
- on Google Compute Engine Virtual Machine Instances.
diff --git a/packages/google-compute-engine-oslogin/packaging/debian/copyright b/packages/google-compute-engine-oslogin/packaging/debian/copyright
deleted file mode 100644
index f1c5775..0000000
--- a/packages/google-compute-engine-oslogin/packaging/debian/copyright
+++ /dev/null
@@ -1,27 +0,0 @@
-Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
-Upstream-Name: google-compute-engine-oslogin
-Upstream-Contact: gc-team@google.com
-
-Files: *
-Copyright: Copyright 2017 Google Inc.
-License: Apache-2.0
-
-Files: debian/*
-Copyright: Copyright 2017 Google Inc.
-License: Apache-2.0
-
-License: Apache-2.0
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- .
- http://www.apache.org/licenses/LICENSE-2.0
- .
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- .
- On Debian systems, the complete text of the Apache version 2.0 license
- can be found in "/usr/share/common-licenses/Apache-2.0".
diff --git a/packages/google-compute-engine-oslogin/packaging/debian/rules b/packages/google-compute-engine-oslogin/packaging/debian/rules
deleted file mode 100755
index 8ae94b8..0000000
--- a/packages/google-compute-engine-oslogin/packaging/debian/rules
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/usr/bin/make -f
-%:
- dh $@
-
-override_dh_auto_install:
- dh_auto_install -- LIBDIR=/lib/$(DEB_HOST_MULTIARCH)
diff --git a/packages/google-compute-engine-oslogin/packaging/debian/source/format b/packages/google-compute-engine-oslogin/packaging/debian/source/format
deleted file mode 100644
index 163aaf8..0000000
--- a/packages/google-compute-engine-oslogin/packaging/debian/source/format
+++ /dev/null
@@ -1 +0,0 @@
-3.0 (quilt)
diff --git a/packages/google-compute-engine-oslogin/packaging/google-compute-engine-oslogin.spec b/packages/google-compute-engine-oslogin/packaging/google-compute-engine-oslogin.spec
deleted file mode 100644
index d9b67bd..0000000
--- a/packages/google-compute-engine-oslogin/packaging/google-compute-engine-oslogin.spec
+++ /dev/null
@@ -1,101 +0,0 @@
-# Copyright 2017 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# For EL7, if building on CentOS, override dist to be el7.
-%if 0%{?rhel} == 7
- %define dist .el7
-%endif
-
-Name: google-compute-engine-oslogin
-Epoch: 1
-Version: %{_version}
-Release: g1%{?dist}
-Summary: OS Login Functionality for Google Compute Engine
-
-License: ASL 2.0
-Source0: %{name}_%{version}.orig.tar.gz
-
-BuildRequires: boost-devel
-BuildRequires: gcc-c++
-BuildRequires: make
-BuildRequires: libcurl
-BuildRequires: json-c-devel
-BuildRequires: pam-devel
-%if 0%{?rhel} == 8
-BuildRequires: python3-policycoreutils
-Requires: python3-policycoreutils
-%else
-BuildRequires: policycoreutils-python
-Requires: policycoreutils-python
-%endif
-Requires: boost-regex
-Requires: json-c
-
-%description
-This package contains several libraries and changes to enable OS Login functionality
-for Google Compute Engine.
-
-%global debug_package %{nil}
-
-%prep
-%setup
-
-%build
-make %{?_smp_mflags} LDLIBS="-lcurl -ljson-c -lboost_regex"
-
-%install
-rm -rf %{buildroot}
-make install DESTDIR=%{buildroot} LIBDIR=/%{_lib} INSTALL_SELINUX=y
-
-%files
-%doc
-/%{_lib}/libnss_oslogin-%{version}.so
-/%{_lib}/libnss_cache_oslogin-%{version}.so
-/%{_lib}/libnss_oslogin.so.2
-/%{_lib}/libnss_cache_oslogin.so.2
-/%{_lib}/security/pam_oslogin_admin.so
-/%{_lib}/security/pam_oslogin_login.so
-/usr/bin/google_authorized_keys
-/usr/bin/google_oslogin_control
-/usr/bin/google_oslogin_nss_cache
-/usr/share/selinux/packages/oslogin.pp
-%{_mandir}/man8/nss-oslogin.8.gz
-%{_mandir}/man8/libnss_oslogin.so.2.8.gz
-%{_mandir}/man8/nss-cache-oslogin.8.gz
-%{_mandir}/man8/libnss_cache_oslogin.so.2.8.gz
-
-%post
-/sbin/ldconfig
-if [ $1 -gt 1 ]; then # This is an upgrade.
- if semodule -l | grep -qi oslogin.el6; then
- echo "Removing old SELinux module for OS Login."
- semodule -r oslogin.el6
- fi
-fi
-echo "Installing SELinux module for OS Login."
-semodule -i /usr/share/selinux/packages/oslogin.pp
-if [ -e /var/google-sudoers.d ]; then
- fixfiles restore /var/google-sudoers.d
-fi
-
-%postun
-/sbin/ldconfig
-if [ $1 = 0 ]; then # This is an uninstall.
- if semodule -l|grep -qi oslogin; then
- echo "Removing SELinux module for OS Login."
- semodule -r oslogin
- fi
-fi
-
-%changelog
diff --git a/packages/google-compute-engine-oslogin/packaging/setup_deb.sh b/packages/google-compute-engine-oslogin/packaging/setup_deb.sh
deleted file mode 100755
index 5b3f893..0000000
--- a/packages/google-compute-engine-oslogin/packaging/setup_deb.sh
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/bin/bash
-# Copyright 2018 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-NAME="google-compute-engine-oslogin"
-VERSION="20190801.00"
-
-DEB=$(cut -d. -f1 </etc/debian_version)
-if [[ -z $DEB ]]; then
- echo "Can't determine debian version of build host"
- exit 1
-fi
-
-working_dir=${PWD}
-if [[ $(basename "$working_dir") != $NAME ]]; then
- echo "Packaging scripts must be run from top of package dir."
- exit 1
-fi
-
-# Build dependencies.
-echo "Installing dependencies."
-sudo apt-get -y install make g++ libcurl4-openssl-dev libjson-c-dev libpam-dev \
- debhelper devscripts build-essential >/dev/null
-
-rm -rf /tmp/debpackage
-mkdir /tmp/debpackage
-tar czvf /tmp/debpackage/${NAME}_${VERSION}.orig.tar.gz --exclude .git \
- --exclude packaging --transform "s/^\./${NAME}-${VERSION}/" .
-
-pushd /tmp/debpackage
-tar xzvf ${NAME}_${VERSION}.orig.tar.gz
-
-cd ${NAME}-${VERSION}
-
-cp -r ${working_dir}/packaging/debian ./
-echo "Building on Debian ${DEB}, modifying latest changelog entry."
-sed -r -i"" "1s/^${NAME} \((.*)\) (.+;.*)/${NAME} (\1+deb${DEB}) \2/" \
- debian/changelog
-
-echo "Starting build"
-DEB_BUILD_OPTIONS=noddebs debuild -us -uc
-
-popd
diff --git a/packages/google-compute-engine-oslogin/packaging/setup_rpm.sh b/packages/google-compute-engine-oslogin/packaging/setup_rpm.sh
deleted file mode 100755
index d0bef7b..0000000
--- a/packages/google-compute-engine-oslogin/packaging/setup_rpm.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-# Copyright 2018 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-NAME="google-compute-engine-oslogin"
-VERSION="20190801.00"
-
-rpm_working_dir=/tmp/rpmpackage/${NAME}-${VERSION}
-working_dir=${PWD}
-if [[ $(basename "$working_dir") != $NAME ]]; then
- echo "Packaging scripts must be run from top of package dir."
- exit 1
-fi
-
-sudo yum -y install rpmdevtools make gcc-c++ json-c \
- libcurl-devel pam-devel boost-devel json-c-devel
-
-if grep -q '^\(CentOS\|Red Hat\)[^0-9]*8\..' /etc/redhat-release; then
- sudo yum -y install python3-policycoreutils
-else
- sudo yum -y install policycoreutils-python
-fi
-
-rm -rf /tmp/rpmpackage
-mkdir -p ${rpm_working_dir}/{SOURCES,SPECS}
-cp packaging/${NAME}.spec ${rpm_working_dir}/SPECS/
-
-tar czvf ${rpm_working_dir}/SOURCES/${NAME}_${VERSION}.orig.tar.gz --exclude .git --exclude packaging --transform "s/^\./${NAME}-${VERSION}/" .
-
-rpmbuild --define "_topdir ${rpm_working_dir}/" --define "_version ${VERSION}" \
- -ba ${rpm_working_dir}/SPECS/${NAME}.spec
diff --git a/packages/google-compute-engine-oslogin/selinux/Makefile b/packages/google-compute-engine-oslogin/selinux/Makefile
deleted file mode 100644
index c858c9d..0000000
--- a/packages/google-compute-engine-oslogin/selinux/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-# SELINUX POLICY
-MOD_BASE = oslogin
-SELINUX_MODULE_SRC = $(MOD_BASE).te
-SELINUX_MOD_FILE = $(MOD_BASE).mod
-SELINUX_FC_FILE = $(MOD_BASE).fc
-SELINUX_MODULE = $(MOD_BASE).pp
-
-all: $(SELINUX_MODULE)
-
-$(SELINUX_MOD_FILE): $(SELINUX_MODULE_SRC)
- checkmodule -M -m -o $(SELINUX_MOD_FILE) $(SELINUX_MODULE_SRC)
-
-$(SELINUX_MODULE): $(SELINUX_MOD_FILE)
- semodule_package -o $(SELINUX_MODULE) -m $(SELINUX_MOD_FILE) -f $(SELINUX_FC_FILE)
-
-clean:
- rm -f $(SELINUX_MODULE) $(SELINUX_MOD_FILE)
diff --git a/packages/google-compute-engine-oslogin/selinux/README.md b/packages/google-compute-engine-oslogin/selinux/README.md
deleted file mode 100644
index b2cc5a9..0000000
--- a/packages/google-compute-engine-oslogin/selinux/README.md
+++ /dev/null
@@ -1,17 +0,0 @@
-## SELinux policy module for OS Login
-
-This module adds specific policy updates which enable OS Login features to
-function on SELinux-enabled systems (currently default on GCE RHEL6/7 images).
-
-It primarily enables `SSHD(8)` to make network calls to the metadata server to
-verify OS Login users, and to create per-user `SUDOERS(5)` files in
-`/var/google-sudoers.d`
-
-### Building the module
-
-The provided Makefile compiles type enforcement and file context files into a
-binary SELinux policy module. It must be compiled on the oldest version of the
-destination OS you intend to support, as binary module versions are not
-backwards compatible. Therefore, this Makefile is not run as part of the normal
-packaging process but is done 'by hand', only when changes are made to the
-policy.
diff --git a/packages/google-compute-engine-oslogin/selinux/oslogin.fc b/packages/google-compute-engine-oslogin/selinux/oslogin.fc
deleted file mode 100644
index 3e70358..0000000
--- a/packages/google-compute-engine-oslogin/selinux/oslogin.fc
+++ /dev/null
@@ -1,2 +0,0 @@
-/var/google-sudoers.d(/.*)? system_u:object_r:google_t:s0
-/var/google-users.d(/.*)? system_u:object_r:google_t:s0
diff --git a/packages/google-compute-engine-oslogin/selinux/oslogin.pp b/packages/google-compute-engine-oslogin/selinux/oslogin.pp
deleted file mode 100644
index 6ec6ed0..0000000
--- a/packages/google-compute-engine-oslogin/selinux/oslogin.pp
+++ /dev/null
Binary files differ
diff --git a/packages/google-compute-engine-oslogin/selinux/oslogin.te b/packages/google-compute-engine-oslogin/selinux/oslogin.te
deleted file mode 100644
index 381f769..0000000
--- a/packages/google-compute-engine-oslogin/selinux/oslogin.te
+++ /dev/null
@@ -1,24 +0,0 @@
-
-module oslogin 1.0;
-
-
-require {
- attribute file_type;
- attribute non_security_file_type;
- type http_port_t;
- type sshd_t;
- class tcp_socket name_connect;
- class file { create getattr setattr write open unlink };
- class dir { search write remove_name add_name };
-}
-
-#============= types ==============
-
-type google_t; # defined in oslogin.fc
-typeattribute google_t file_type, non_security_file_type;
-
-#============= sshd_t ==============
-
-allow sshd_t google_t:file { create getattr setattr write open unlink };
-allow sshd_t google_t:dir { search write remove_name add_name };
-allow sshd_t http_port_t:tcp_socket name_connect;
diff --git a/packages/google-compute-engine-oslogin/src/Makefile b/packages/google-compute-engine-oslogin/src/Makefile
deleted file mode 100644
index 8b5d339..0000000
--- a/packages/google-compute-engine-oslogin/src/Makefile
+++ /dev/null
@@ -1,86 +0,0 @@
-SHELL = /bin/sh
-TOPDIR = $(realpath ..)
-
-VERSION = 20190801.00
-
-CPPFLAGS = -Iinclude -I/usr/include/json-c
-FLAGS = -fPIC -Wall -g
-CFLAGS = $(FLAGS) -Wstrict-prototypes
-CXXFLAGS = $(FLAGS)
-
-LDFLAGS = -shared -Wl,-soname,$(SONAME)
-LDLIBS = -lcurl -ljson-c
-PAMLIBS = -lpam $(LDLIBS)
-
-# Paths which should be overrideable.
-
-PREFIX = /usr
-LIBDIR = $(PREFIX)/lib
-BINDIR = $(PREFIX)/bin
-PAMDIR = $(LIBDIR)/security
-MANDIR = /usr/share/man
-
-NSS_OSLOGIN_SONAME = libnss_oslogin.so.2
-NSS_CACHE_OSLOGIN_SONAME = libnss_cache_oslogin.so.2
-
-NSS_OSLOGIN = libnss_oslogin-$(VERSION).so
-NSS_CACHE_OSLOGIN = libnss_cache_oslogin-$(VERSION).so
-
-PAM_LOGIN = pam_oslogin_login.so
-PAM_ADMIN = pam_oslogin_admin.so
-
-BINARIES = google_oslogin_nss_cache google_authorized_keys
-
-all : $(NSS_OSLOGIN) $(NSS_CACHE_OSLOGIN) $(PAM_LOGIN) $(PAM_ADMIN) $(BINARIES)
-
-clean :
- rm -f $(BINARIES)
- find . -type f \( -iname '*.o' -o -iname '*.so' \) -delete
-
-.PHONY : all clean install
-
-# NSS modules.
-
-$(NSS_OSLOGIN) : SONAME = $(NSS_OSLOGIN_SONAME)
-$(NSS_OSLOGIN) : nss/nss_oslogin.o utils.o
- $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $^ -o $@ $(LDLIBS)
-
-$(NSS_CACHE_OSLOGIN) : SONAME = $(NSS_CACHE_OSLOGIN_SONAME)
-$(NSS_CACHE_OSLOGIN) : nss/nss_cache_oslogin.o nss/compat/getpwent_r.o utils.o
- $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $^ -o $@ $(LDLIBS)
-
-# PAM modules
-
-$(PAM_LOGIN) : pam/pam_oslogin_login.o utils.o
- $(CXX) $(CXXFLAGS) $(CPPFLAGS) -shared $^ -o $@ $(PAMLIBS)
-
-$(PAM_ADMIN) : pam/pam_oslogin_admin.o utils.o
- $(CXX) $(CXXFLAGS) $(CPPFLAGS) -shared $^ -o $@ $(PAMLIBS)
-
-# Utilities.
-
-google_authorized_keys : authorized_keys/authorized_keys.o utils.o
- $(CXX) $(CXXFLAGS) $(CPPFLAGS) $^ -o $@ $(LDLIBS)
-
-google_oslogin_nss_cache: cache_refresh/cache_refresh.o utils.o
- $(CXX) $(CXXFLAGS) $(CPPFLAGS) $^ -o $@ $(LDLIBS)
-
-install: all
- install -d $(DESTDIR)$(LIBDIR)
- install -d $(DESTDIR)$(PAMDIR)
- install -d $(DESTDIR)$(BINDIR)
- install -d $(DESTDIR)$(MANDIR)/man8
- install -m 0644 -t $(DESTDIR)$(LIBDIR) $(NSS_OSLOGIN) $(NSS_CACHE_OSLOGIN)
- ln -sf $(NSS_OSLOGIN) $(DESTDIR)$(LIBDIR)/$(NSS_OSLOGIN_SONAME)
- ln -sf $(NSS_CACHE_OSLOGIN) $(DESTDIR)$(LIBDIR)/$(NSS_CACHE_OSLOGIN_SONAME)
- install -m 0644 -t $(DESTDIR)$(PAMDIR) $(PAM_ADMIN) $(PAM_LOGIN)
- install -m 0755 -t $(DESTDIR)$(BINDIR) $(BINARIES) $(TOPDIR)/google_oslogin_control
- install -m 0644 -t $(DESTDIR)$(MANDIR)/man8 $(TOPDIR)/man/nss-oslogin.8 $(TOPDIR)/man/nss-cache-oslogin.8
- gzip -9 $(DESTDIR)$(MANDIR)/man8/nss-oslogin.8
- gzip -9 $(DESTDIR)$(MANDIR)/man8/nss-cache-oslogin.8
- ln -sf nss-oslogin.8.gz $(DESTDIR)$(MANDIR)/man8/$(NSS_OSLOGIN_SONAME).8.gz
- ln -sf nss-cache-oslogin.8.gz $(DESTDIR)$(MANDIR)/man8/$(NSS_CACHE_OSLOGIN_SONAME).8.gz
-ifdef INSTALL_SELINUX
- install -d $(DESTDIR)/usr/share/selinux/packages
- install -m 0644 -t $(DESTDIR)/usr/share/selinux/packages $(TOPDIR)/selinux/oslogin.pp
-endif
diff --git a/packages/google-compute-engine-oslogin/src/authorized_keys/authorized_keys.cc b/packages/google-compute-engine-oslogin/src/authorized_keys/authorized_keys.cc
deleted file mode 100644
index 3eda59c..0000000
--- a/packages/google-compute-engine-oslogin/src/authorized_keys/authorized_keys.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <iostream>
-#include <sstream>
-#include <string>
-
-#include <oslogin_utils.h>
-
-using std::cout;
-using std::endl;
-using std::string;
-
-using oslogin_utils::HttpGet;
-using oslogin_utils::ParseJsonToSuccess;
-using oslogin_utils::ParseJsonToKey;
-using oslogin_utils::ParseJsonToEmail;
-using oslogin_utils::ParseJsonToSshKeys;
-using oslogin_utils::UrlEncode;
-using oslogin_utils::kMetadataServerUrl;
-
-int main(int argc, char* argv[]) {
- if (argc != 2) {
- cout << "usage: authorized_keys [username]" << endl;
- return 1;
- }
- std::stringstream url;
- url << kMetadataServerUrl << "users?username=" << UrlEncode(argv[1]);
- string user_response;
- long http_code = 0;
- if (!HttpGet(url.str(), &user_response, &http_code) ||
- user_response.empty() || http_code != 200) {
- if (http_code == 404) {
- // Return 0 if the user is not an oslogin user. If we returned a failure
- // code, we would populate auth.log with useless error messages.
- return 0;
- }
- return 1;
- }
- string email;
- if (!ParseJsonToEmail(user_response, &email) || email.empty()) {
- return 1;
- }
- // Redundantly verify that this user has permission to log in to this VM.
- // Normally the PAM module determines this, but in the off chance a transient
- // error causes the PAM module to permit a user without login permissions,
- // perform the same check here. If this fails, we can guarantee that we won't
- // accidentally allow a user to log in without permissions.
- url.str("");
- url << kMetadataServerUrl << "authorize?email=" << UrlEncode(email)
- << "&policy=login";
- string auth_response;
- if (!HttpGet(url.str(), &auth_response, &http_code) || http_code != 200 ||
- auth_response.empty()) {
- return 1;
- }
- if (!ParseJsonToSuccess(auth_response)) {
- return 1;
- }
- // At this point, we've verified the user can log in. Grab the ssh keys from
- // the user response.
- std::vector<string> ssh_keys = ParseJsonToSshKeys(user_response);
- for (int i = 0; i < ssh_keys.size(); i++) {
- cout << ssh_keys[i] << endl;
- }
- return 0;
-}
diff --git a/packages/google-compute-engine-oslogin/src/cache_refresh/cache_refresh.cc b/packages/google-compute-engine-oslogin/src/cache_refresh/cache_refresh.cc
deleted file mode 100644
index bc4a10c..0000000
--- a/packages/google-compute-engine-oslogin/src/cache_refresh/cache_refresh.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2018 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <errno.h>
-#include <nss.h>
-#include <pthread.h>
-#include <pwd.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#include <fstream>
-
-#include <compat.h>
-#include <oslogin_utils.h>
-
-
-using oslogin_utils::BufferManager;
-using oslogin_utils::MutexLock;
-using oslogin_utils::NssCache;
-
-// File paths for the nss cache file.
-static const char kDefaultFilePath[] = K_DEFAULT_FILE_PATH;
-static const char kDefaultBackupFilePath[] = K_DEFAULT_BACKUP_FILE_PATH;
-
-// Local NSS Cache size. This affects the maximum number of passwd entries per
-// http request.
-static const uint64_t kNssCacheSize = 2048;
-
-// Passwd buffer size. We are guaranteed that a single OS Login user will not
-// exceed 32k.
-static const uint64_t kPasswdBufferSize = 32768;
-
-static NssCache nss_cache(kNssCacheSize);
-
-static pthread_mutex_t cache_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-int main(int argc, char* argv[]) {
- int error_code = 0;
- // Temporary buffer to hold passwd entries before writing.
- char buffer[kPasswdBufferSize];
- struct passwd pwd;
-
- // Perform the writes under a global lock.
- MutexLock ml(&cache_mutex);
- nss_cache.Reset();
-
- // Check if there is a cache already.
- struct stat stat_buf;
- bool backup = !stat(kDefaultFilePath, &stat_buf);
- if (backup) {
- // Write a backup file first, in case lookup fails.
- error_code = rename(kDefaultFilePath, kDefaultBackupFilePath);
- if (error_code) {
- openlog("nss_cache_oslogin", LOG_PID, LOG_USER);
- syslog(LOG_ERR, "Could not create backup file.");
- closelog();
- return error_code;
- }
- }
-
- std::ofstream cache_file(kDefaultFilePath);
- if (cache_file.fail()) {
- openlog("nss_cache_oslogin", LOG_PID, LOG_USER);
- syslog(LOG_ERR, "Failed to open file %s.", kDefaultFilePath);
- closelog();
- return -1;
- }
- chown(kDefaultFilePath, 0, 0);
- chmod(kDefaultFilePath, S_IRUSR | S_IWUSR | S_IROTH);
-
- while (!nss_cache.OnLastPage() || nss_cache.HasNextPasswd()) {
- BufferManager buffer_manager(buffer, kPasswdBufferSize);
- if (!nss_cache.NssGetpwentHelper(&buffer_manager, &pwd, &error_code)) {
- break;
- }
- cache_file << pwd.pw_name << ":" << pwd.pw_passwd << ":" << pwd.pw_uid
- << ":" << pwd.pw_gid << ":" << pwd.pw_gecos << ":" << pwd.pw_dir
- << ":" << pwd.pw_shell << "\n";
- }
- cache_file.close();
-
- // Check for errors.
- if (error_code) {
- openlog("nss_cache_oslogin", LOG_PID, LOG_USER);
- if (error_code == ERANGE) {
- syslog(LOG_ERR, "Received unusually large passwd entry.");
- } else if (error_code == EINVAL) {
- syslog(LOG_ERR, "Encountered malformed passwd entry.");
- } else {
- syslog(LOG_ERR, "Unknown error while retrieving passwd entry.");
- }
- // Restore the backup.
- if (backup) {
- if (rename(kDefaultBackupFilePath, kDefaultFilePath)) {
- syslog(LOG_ERR, "Could not restore data from backup file.");
- }
- }
- closelog();
- }
-
- // Remove the backup file on success.
- if (!error_code && backup) {
- remove(kDefaultBackupFilePath);
- }
- return error_code;
-}
diff --git a/packages/google-compute-engine-oslogin/src/include/compat.h b/packages/google-compute-engine-oslogin/src/include/compat.h
deleted file mode 100644
index 84a1a6f..0000000
--- a/packages/google-compute-engine-oslogin/src/include/compat.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2018 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef OSLOGIN_COMPAT_H
-#define OSLOGIN_COMPAT_H
-
-#ifdef __FreeBSD__
-
-#include <nsswitch.h>
-
-#define DECLARE_NSS_METHOD_TABLE(name, ...) \
- static ns_mtab name[] = {__VA_ARGS__};
-
-#define NSS_METHOD(method, func) { \
- .database = NSDB_PASSWD, \
- .name = #method, \
- .method = __nss_compat_ ## method, \
- .mdata = (void*)func \
-}
-
-#define NSS_REGISTER_METHODS(methods) ns_mtab * \
-nss_module_register (const char *name, unsigned int *size, \
- nss_module_unregister_fn *unregister) \
-{ \
- *size = sizeof (methods) / sizeof (methods[0]); \
- *unregister = NULL; \
- return (methods); \
-}
-
-#define NSS_CACHE_OSLOGIN_PATH "/usr/local/etc/oslogin_passwd.cache"
-#define K_DEFAULT_FILE_PATH "/usr/local/etc/oslogin_passwd.cache"
-#define K_DEFAULT_BACKUP_FILE_PATH "/usr/local/etc/oslogin_passwd.cache.bak"
-#define PAM_SYSLOG(pamh, ...) syslog(__VA_ARGS__)
-#define DEFAULT_SHELL "/bin/sh"
-
-#else /* __FreeBSD__ */
-
-#include <security/pam_ext.h>
-
-#define DECLARE_NSS_METHOD_TABLE(name, ...)
-#define NSS_CACHE_OSLOGIN_PATH "/etc/oslogin_passwd.cache"
-#define NSS_METHOD_PROTOTYPE(m)
-#define NSS_REGISTER_METHODS(methods)
-#define K_DEFAULT_FILE_PATH "/etc/oslogin_passwd.cache"
-#define K_DEFAULT_BACKUP_FILE_PATH "/etc/oslogin_passwd.cache.bak"
-#define PAM_SYSLOG pam_syslog
-#define DEFAULT_SHELL "/bin/bash"
-
-#endif /* __FreeBSD__ */
-
-#endif /* OSLOGIN_COMPAT_H */
diff --git a/packages/google-compute-engine-oslogin/src/include/nss_cache_oslogin.h b/packages/google-compute-engine-oslogin/src/include/nss_cache_oslogin.h
deleted file mode 100644
index 25c7274..0000000
--- a/packages/google-compute-engine-oslogin/src/include/nss_cache_oslogin.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2018 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <errno.h>
-#include <nss.h>
-#include <stdlib.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <time.h>
-#include <unistd.h>
-
-#ifndef NSS_CACHE_OSLOGIN_H
-#define NSS_CACHE_OSLOGIN_H
-
-#ifdef DEBUG
-#undef DEBUG
-#define DEBUG(fmt, args...) \
- do { \
- fprintf(stderr, fmt, ##args); \
- } while (0)
-#else
-#define DEBUG(fmt, ...) \
- do { \
- } while (0)
-#endif /* DEBUG */
-
-#define NSS_CACHE_OSLOGIN_PATH_LENGTH 255
-extern char *_nss_cache_oslogin_setpwent_path(const char *path);
-
-enum nss_cache_oslogin_match {
- NSS_CACHE_OSLOGIN_EXACT = 0,
- NSS_CACHE_OSLOGIN_HIGH = 1,
- NSS_CACHE_OSLOGIN_LOW = 2,
- NSS_CACHE_OSLOGIN_ERROR = 3,
-};
-
-struct nss_cache_oslogin_args {
- char *system_filename;
- char *sorted_filename;
- void *lookup_function;
- void *lookup_value;
- void *lookup_result;
- char *buffer;
- size_t buflen;
- char *lookup_key;
- size_t lookup_key_length;
-};
-
-#endif /* NSS_CACHE_OSLOGIN_H */
diff --git a/packages/google-compute-engine-oslogin/src/include/oslogin_utils.h b/packages/google-compute-engine-oslogin/src/include/oslogin_utils.h
deleted file mode 100644
index 82763bf..0000000
--- a/packages/google-compute-engine-oslogin/src/include/oslogin_utils.h
+++ /dev/null
@@ -1,238 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <grp.h>
-#include <pthread.h>
-#include <pwd.h>
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#define TOTP "TOTP"
-#define AUTHZEN "AUTHZEN"
-#define INTERNAL_TWO_FACTOR "INTERNAL_TWO_FACTOR"
-#define IDV_PREREGISTERED_PHONE "IDV_PREREGISTERED_PHONE"
-
-using std::string;
-using std::vector;
-
-namespace oslogin_utils {
-
-// Metadata server URL.
-static const char kMetadataServerUrl[] =
- "http://metadata.google.internal/computeMetadata/v1/oslogin/";
-
-// BufferManager encapsulates and manages a buffer and length. This class is not
-// thread safe.
-class BufferManager {
- public:
- // Create a BufferManager that will dole out chunks of buf as requested.
- BufferManager(char* buf, size_t buflen);
-
- // Copies a string to the buffer and sets the buffer to point to that
- // string. Copied string is guaranteed to be null-terminated.
- // Returns false and sets errnop if there is not enough space left in the
- // buffer for the string.
- bool AppendString(const string& value, char** buffer, int* errnop);
-
- // Return a pointer to a buffer of size bytes. Returns NULL and sets errnop to
- // ERANGE if there is not enough space left in the buffer for the request.
- void* Reserve(size_t bytes, int* errnop);
-
- private:
- // Whether there is space available in the buffer.
- bool CheckSpaceAvailable(size_t bytes_to_write) const;
-
- char* buf_;
- size_t buflen_;
-
- // Not copyable or assignable.
- BufferManager& operator=(const BufferManager&);
- BufferManager(const BufferManager&);
-};
-
-// Challenge represents a security challenge available to the user.
-class Challenge {
- public:
- int id;
- string type;
- string status;
-};
-
-class Group {
- public:
- int64_t gid;
- string name;
-};
-
-// NssCache caches passwd entries for getpwent_r. This is used to prevent making
-// an HTTP call on every getpwent_r invocation. Stores up to cache_size entries
-// at a time. This class is not thread safe.
-class NssCache {
- public:
- explicit NssCache(int cache_size);
-
- // Clears and resets the NssCache.
- void Reset();
-
- // Whether the cache has a next passwd entry.
- bool HasNextPasswd();
-
- // Whether the cache has reached the last page of the database.
- bool OnLastPage() { return on_last_page_; }
-
- // Grabs the next passwd entry. Returns true on success. Sets errnop on
- // failure.
- bool GetNextPasswd(BufferManager* buf, passwd* result, int* errnop);
-
- // Loads a json array of passwd entries in the cache, starting at the
- // beginning of the cache. This will remove all previous entries in the cache.
- // response is expected to be a JSON array of passwd entries. Returns
- // true on success.
- bool LoadJsonArrayToCache(string response);
-
- // Helper method that effectively implements the getpwent_r nss method. Each
- // call will iterate through the OsLogin database and return the next entry.
- // Internally, the cache will keep track of pages of passwd entries, and will
- // make an http call to the server if necessary to retrieve additional
- // entries. Returns whether passwd retrieval was successful. If true, the
- // passwd result will contain valid data.
- bool NssGetpwentHelper(BufferManager* buf, struct passwd* result,
- int* errnop);
-
- // Returns the page token for requesting the next page of passwd entries.
- string GetPageToken() { return page_token_; }
-
- private:
- // The maximum size of the cache.
- int cache_size_;
-
- // Vector of passwds. These are represented as stringified json object.
- std::vector<std::string> passwd_cache_;
-
- // The page token for requesting the next page of passwds.
- std::string page_token_;
-
- // Index for requesting the next passwd from the cache.
- uint32_t index_;
-
- // Whether the NssCache has reached the last page of the database.
- bool on_last_page_;
-
- // Not copyable or assignable.
- NssCache& operator=(const NssCache&);
- NssCache(const NssCache&);
-};
-
-// Auto locks and unlocks a given mutex on construction/destruction. Does NOT
-// take ownership of the mutex.
-class MutexLock {
- public:
- explicit MutexLock(pthread_mutex_t* mutex) : mutex_(mutex) {
- pthread_mutex_lock(mutex_);
- }
-
- ~MutexLock() { pthread_mutex_unlock(mutex_); }
-
- private:
- // The mutex to lock/unlock
- pthread_mutex_t* const mutex_;
-
- // Not copyable or assignable.
- MutexLock& operator=(const MutexLock);
- MutexLock(const MutexLock&);
-};
-
-// Callback invoked when Curl completes a request.
-size_t OnCurlWrite(void* buf, size_t size, size_t nmemb, void* userp);
-
-// Uses Curl to issue a GET request to the given url. Returns whether the
-// request was successful. If successful, the result from the server will be
-// stored in response, and the HTTP response code will be stored in http_code.
-bool HttpGet(const string& url, string* response, long* http_code);
-bool HttpPost(const string& url, const string& data, string* response,
- long* http_code);
-
-// Returns whether user_name is a valid OsLogin user name.
-bool ValidateUserName(const string& user_name);
-
-// URL encodes the given parameter. Returns the encoded parameter.
-std::string UrlEncode(const string& param);
-
-// Returns true if the given passwd contains valid fields. If pw_dir, pw_shell,
-// or pw_passwd are not set, this will populate these entries with default
-// values.
-bool ValidatePasswd(struct passwd* result, BufferManager* buf, int* errnop);
-
-// Adds users and associated array of char* to provided buffer and store pointer
-// to array in result.gr_mem.
-bool AddUsersToGroup(std::vector<string> users, struct group* result,
- BufferManager* buf, int* errnop);
-
-// Iterates through all groups until one matching provided group is found,
-// replacing gr_name with a buffermanager provided string.
-bool FindGroup(struct group* grp, BufferManager* buf, int* errnop);
-
-// Iterates through all users for a group, storing results in a provided string
-// vector.
-bool GetUsersForGroup(string groupname, std::vector<string>* users,
- int* errnop);
-
-// Iterates through all groups for a user, storing results in a provided string
-// vector.
-bool GetGroupsForUser(string username, std::vector<Group>* groups, int* errnop);
-
-// Parses a JSON groups response, storing results in a provided Group vector.
-bool ParseJsonToGroups(const string& json, std::vector<Group>* groups);
-
-// Parses a JSON users response, storing results in a provided string vector.
-bool ParseJsonToUsers(const string& json, std::vector<string>* users);
-
-// Parses a JSON LoginProfiles response for SSH keys. Returns a vector of valid
-// ssh_keys. A key is considered valid if it's expiration date is greater than
-// current unix time.
-std::vector<string> ParseJsonToSshKeys(const string& json);
-
-// Parses a JSON object and returns the value associated with a given key.
-bool ParseJsonToKey(const string& json, const string& key, string* response);
-
-// Parses a JSON LoginProfiles response and returns the email under the "name"
-// field.
-bool ParseJsonToEmail(const string& json, string* email);
-
-// Parses a JSON LoginProfiles response and populates the passwd struct with the
-// corresponding values set in the JSON object. Returns whether the parse was
-// successful or not. If unsuccessful, errnop will also be set.
-bool ParseJsonToPasswd(const string& response, struct passwd* result,
- BufferManager* buf, int* errnop);
-
-// Parses a JSON adminLogin or login response and returns whether the user has
-// the requested privilege.
-bool ParseJsonToSuccess(const string& json);
-
-// Parses a JSON startSession response into a vector of Challenge objects.
-bool ParseJsonToChallenges(const string& json, vector<Challenge>* challenges);
-
-// Calls the startSession API.
-bool StartSession(const string& email, string* response);
-
-// Calls the continueSession API.
-bool ContinueSession(bool alt, const string& email, const string& user_token,
- const string& session_id, const Challenge& challenge,
- string* response);
-
-// Returns user information from the metadata server.
-bool GetUser(const string& username, string* response);
-} // namespace oslogin_utils
diff --git a/packages/google-compute-engine-oslogin/src/nss/compat/getpwent_r.c b/packages/google-compute-engine-oslogin/src/nss/compat/getpwent_r.c
deleted file mode 100644
index b1be6fc..0000000
--- a/packages/google-compute-engine-oslogin/src/nss/compat/getpwent_r.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * ----------------------------------------------------------------------
- * Copyright © 2005-2014 Rich Felker, et al.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * ----------------------------------------------------------------------
- *
- * Adapted from http://www.musl-libc.org/ for libnss-cache
- * Copyright © 2015 Kevin Bowling <k@kev009.com>
- */
-
-#include <sys/param.h>
-
-#ifdef BSD
-
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-
-static unsigned atou(char **s)
-{
- unsigned x;
- for (x=0; **s-'0'<10U; ++*s) x=10*x+(**s-'0');
- return x;
-}
-
-int fgetpwent_r(FILE *f, struct passwd *pw, char *line, size_t size, struct passwd **res)
-{
- char *s;
- int rv = 0;
- for (;;) {
- line[size-1] = '\xff';
- if ( (fgets(line, size, f) == NULL) || ferror(f) || line[size-1] != '\xff' ) {
- rv = (line[size-1] != '\xff') ? ERANGE : ENOENT;
- line = 0;
- pw = 0;
- break;
- }
- line[strcspn(line, "\n")] = 0;
-
- s = line;
- pw->pw_name = s++;
- if (!(s = strchr(s, ':'))) continue;
-
- *s++ = 0; pw->pw_passwd = s;
- if (!(s = strchr(s, ':'))) continue;
-
- *s++ = 0; pw->pw_uid = atou(&s);
- if (*s != ':') continue;
-
- *s++ = 0; pw->pw_gid = atou(&s);
- if (*s != ':') continue;
-
- *s++ = 0; pw->pw_gecos = s;
- if (!(s = strchr(s, ':'))) continue;
-
- *s++ = 0; pw->pw_dir = s;
- if (!(s = strchr(s, ':'))) continue;
-
- *s++ = 0; pw->pw_shell = s;
- break;
- }
- *res = pw;
- if (rv) errno = rv;
- return rv;
-}
-
-#endif // ifdef BSD
diff --git a/packages/google-compute-engine-oslogin/src/nss/nss_cache_oslogin.c b/packages/google-compute-engine-oslogin/src/nss/nss_cache_oslogin.c
deleted file mode 100644
index 55bb78d..0000000
--- a/packages/google-compute-engine-oslogin/src/nss/nss_cache_oslogin.c
+++ /dev/null
@@ -1,274 +0,0 @@
-// Copyright 2018 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// An NSS module which adds supports for file /etc/oslogin_passwd.cache
-
-#include <nss_cache_oslogin.h>
-#include <compat.h>
-
-#include <sys/mman.h>
-
-// Locking implementation: use pthreads.
-#include <pthread.h>
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-#define NSS_CACHE_OSLOGIN_LOCK() \
- do { \
- pthread_mutex_lock(&mutex); \
- } while (0)
-#define NSS_CACHE_OSLOGIN_UNLOCK() \
- do { \
- pthread_mutex_unlock(&mutex); \
- } while (0)
-
-static FILE *p_file = NULL;
-static char p_filename[NSS_CACHE_OSLOGIN_PATH_LENGTH] = NSS_CACHE_OSLOGIN_PATH;
-#ifdef BSD
-extern int fgetpwent_r(FILE *, struct passwd *, char *, size_t,
- struct passwd **);
-#endif // ifdef BSD
-
-/* Common return code routine for all *ent_r_locked functions.
- * We need to return TRYAGAIN if the underlying files guy raises ERANGE,
- * so that our caller knows to try again with a bigger buffer.
- */
-
-static inline enum nss_status _nss_cache_oslogin_ent_bad_return_code(
- int errnoval) {
- enum nss_status ret;
-
- switch (errnoval) {
- case ERANGE:
- DEBUG("ERANGE: Try again with a bigger buffer\n");
- ret = NSS_STATUS_TRYAGAIN;
- break;
- case ENOENT:
- default:
- DEBUG("ENOENT or default case: Not found\n");
- ret = NSS_STATUS_NOTFOUND;
- };
- return ret;
-}
-
-//
-// Routines for passwd map defined below here
-//
-
-// _nss_cache_oslogin_pwuid_wrap()
-// Internal wrapper for binary searches, using uid-specific calls.
-
-static enum nss_cache_oslogin_match _nss_cache_oslogin_pwuid_wrap(
- FILE *file, struct nss_cache_oslogin_args *args) {
- struct passwd *result = args->lookup_result;
- uid_t *uid = args->lookup_value;
-
- if (fgetpwent_r(file, result, args->buffer, args->buflen, &result) == 0) {
- if (result->pw_uid == *uid) {
- DEBUG("SUCCESS: found user %d:%s\n", result->pw_uid, result->pw_name);
- return NSS_CACHE_OSLOGIN_EXACT;
- }
- DEBUG("Failed match at uid %d\n", result->pw_uid);
- if (result->pw_uid > *uid) {
- return NSS_CACHE_OSLOGIN_HIGH;
- } else {
- return NSS_CACHE_OSLOGIN_LOW;
- }
- }
-
- return NSS_CACHE_OSLOGIN_ERROR;
-}
-
-// _nss_cache_oslogin_pwnam_wrap()
-// Internal wrapper for binary searches, using username-specific calls.
-
-static enum nss_cache_oslogin_match _nss_cache_oslogin_pwnam_wrap(
- FILE *file, struct nss_cache_oslogin_args *args) {
- struct passwd *result = args->lookup_result;
- char *name = args->lookup_value;
- int ret;
-
- if (fgetpwent_r(file, result, args->buffer, args->buflen, &result) == 0) {
- ret = strcoll(result->pw_name, name);
- if (ret == 0) {
- DEBUG("SUCCESS: found user %s\n", result->pw_name);
- return NSS_CACHE_OSLOGIN_EXACT;
- }
- DEBUG("Failed match at name %s\n", result->pw_name);
- if (ret > 0) {
- return NSS_CACHE_OSLOGIN_HIGH;
- } else {
- return NSS_CACHE_OSLOGIN_LOW;
- }
- }
-
- return NSS_CACHE_OSLOGIN_ERROR;
-}
-
-// _nss_cache_oslogin_setpwent_locked()
-// Internal setup routine
-
-static enum nss_status _nss_cache_oslogin_setpwent_locked(void) {
- DEBUG("%s %s\n", "Opening", p_filename);
- p_file = fopen(p_filename, "r");
-
- if (p_file) {
- return NSS_STATUS_SUCCESS;
- } else {
- return NSS_STATUS_UNAVAIL;
- }
-}
-
-// _nss_cache_oslogin_setpwent()
-// Called by NSS to open the passwd file
-// 'stayopen' parameter is ignored.
-
-enum nss_status _nss_cache_oslogin_setpwent(int stayopen) {
- enum nss_status ret;
- NSS_CACHE_OSLOGIN_LOCK();
- ret = _nss_cache_oslogin_setpwent_locked();
- NSS_CACHE_OSLOGIN_UNLOCK();
- return ret;
-}
-
-// _nss_cache_oslogin_endpwent_locked()
-// Internal close routine
-
-static enum nss_status _nss_cache_oslogin_endpwent_locked(void) {
- DEBUG("Closing passwd.cache\n");
- if (p_file) {
- fclose(p_file);
- p_file = NULL;
- }
- return NSS_STATUS_SUCCESS;
-}
-
-// _nss_cache_oslogin_endpwent()
-// Called by NSS to close the passwd file
-
-enum nss_status _nss_cache_oslogin_endpwent(void) {
- enum nss_status ret;
- NSS_CACHE_OSLOGIN_LOCK();
- ret = _nss_cache_oslogin_endpwent_locked();
- NSS_CACHE_OSLOGIN_UNLOCK();
- return ret;
-}
-
-// _nss_cache_oslogin_getpwent_r_locked()
-// Called internally to return the next entry from the passwd file
-
-static enum nss_status _nss_cache_oslogin_getpwent_r_locked(
- struct passwd *result, char *buffer, size_t buflen, int *errnop) {
- enum nss_status ret = NSS_STATUS_SUCCESS;
-
- if (p_file == NULL) {
- DEBUG("p_file == NULL, going to setpwent\n");
- ret = _nss_cache_oslogin_setpwent_locked();
- }
-
- if (ret == NSS_STATUS_SUCCESS) {
- if (fgetpwent_r(p_file, result, buffer, buflen, &result) == 0) {
- DEBUG("Returning user %d:%s\n", result->pw_uid, result->pw_name);
- } else {
- if (errno == ENOENT) {
- errno = 0;
- }
- *errnop = errno;
- ret = _nss_cache_oslogin_ent_bad_return_code(*errnop);
- }
- }
-
- return ret;
-}
-
-// _nss_cache_oslogin_getpwent_r()
-// Called by NSS to look up next entry in passwd file
-
-enum nss_status _nss_cache_oslogin_getpwent_r(struct passwd *result,
- char *buffer, size_t buflen,
- int *errnop) {
- enum nss_status ret;
- NSS_CACHE_OSLOGIN_LOCK();
- ret = _nss_cache_oslogin_getpwent_r_locked(result, buffer, buflen, errnop);
- NSS_CACHE_OSLOGIN_UNLOCK();
- return ret;
-}
-
-// _nss_cache_oslogin_getpwuid_r()
-// Find a user account by uid
-
-enum nss_status _nss_cache_oslogin_getpwuid_r(uid_t uid, struct passwd *result,
- char *buffer, size_t buflen,
- int *errnop) {
- enum nss_status ret;
-
- NSS_CACHE_OSLOGIN_LOCK();
- ret = _nss_cache_oslogin_setpwent_locked();
-
- if (ret == NSS_STATUS_SUCCESS) {
- while ((ret = _nss_cache_oslogin_getpwent_r_locked(
- result, buffer, buflen, errnop)) == NSS_STATUS_SUCCESS) {
- if (result->pw_uid == uid) break;
- }
- }
-
- _nss_cache_oslogin_endpwent_locked();
- NSS_CACHE_OSLOGIN_UNLOCK();
-
- return ret;
-}
-
-// _nss_cache_oslogin_getpwnam_r()
-// Find a user account by name
-
-enum nss_status _nss_cache_oslogin_getpwnam_r(const char *name,
- struct passwd *result,
- char *buffer, size_t buflen,
- int *errnop) {
- enum nss_status ret;
-
- NSS_CACHE_OSLOGIN_LOCK();
- ret = _nss_cache_oslogin_setpwent_locked();
-
- if (ret == NSS_STATUS_SUCCESS) {
- while ((ret = _nss_cache_oslogin_getpwent_r_locked(
- result, buffer, buflen, errnop)) == NSS_STATUS_SUCCESS) {
- if (!strcmp(result->pw_name, name)) break;
- }
- }
-
- _nss_cache_oslogin_endpwent_locked();
- NSS_CACHE_OSLOGIN_UNLOCK();
-
- return ret;
-}
-
-NSS_METHOD_PROTOTYPE(__nss_compat_getpwnam_r);
-NSS_METHOD_PROTOTYPE(__nss_compat_getpwuid_r);
-NSS_METHOD_PROTOTYPE(__nss_compat_getpwent_r);
-NSS_METHOD_PROTOTYPE(__nss_compat_setpwent);
-NSS_METHOD_PROTOTYPE(__nss_compat_endpwent);
-
-DECLARE_NSS_METHOD_TABLE(methods,
- { NSDB_PASSWD, "getpwnam_r", __nss_compat_getpwnam_r,
- (void*)_nss_cache_oslogin_getpwnam_r },
- { NSDB_PASSWD, "getpwuid_r", __nss_compat_getpwuid_r,
- (void*)_nss_cache_oslogin_getpwuid_r },
- { NSDB_PASSWD, "getpwent_r", __nss_compat_getpwent_r,
- (void*)_nss_cache_oslogin_getpwent_r },
- { NSDB_PASSWD, "endpwent", __nss_compat_endpwent,
- (void*)_nss_cache_oslogin_endpwent },
- { NSDB_PASSWD, "setpwent", __nss_compat_setpwent,
- (void*)_nss_cache_oslogin_setpwent },
-)
-
-NSS_REGISTER_METHODS(methods)
diff --git a/packages/google-compute-engine-oslogin/src/nss/nss_oslogin.cc b/packages/google-compute-engine-oslogin/src/nss/nss_oslogin.cc
deleted file mode 100644
index 2a34c83..0000000
--- a/packages/google-compute-engine-oslogin/src/nss/nss_oslogin.cc
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <compat.h>
-#include <curl/curl.h>
-#include <errno.h>
-#include <grp.h>
-#include <nss.h>
-#include <oslogin_utils.h>
-#include <pthread.h>
-#include <pwd.h>
-#include <string.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <syslog.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-#include <iostream>
-#include <sstream>
-#include <string>
-
-using std::string;
-
-using oslogin_utils::AddUsersToGroup;
-using oslogin_utils::BufferManager;
-using oslogin_utils::FindGroup;
-using oslogin_utils::GetGroupsForUser;
-using oslogin_utils::GetUsersForGroup;
-using oslogin_utils::Group;
-using oslogin_utils::HttpGet;
-using oslogin_utils::kMetadataServerUrl;
-using oslogin_utils::MutexLock;
-using oslogin_utils::NssCache;
-using oslogin_utils::ParseJsonToPasswd;
-using oslogin_utils::UrlEncode;
-
-// Size of the NssCache. This also determines how many users will be requested
-// per HTTP call.
-static const uint64_t kNssCacheSize = 2048;
-
-// NssCache for storing passwd entries.
-static NssCache nss_cache(kNssCacheSize);
-
-// Protects access to nss_cache.
-static pthread_mutex_t cache_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-extern "C" {
-
-// Get a passwd entry by id.
-enum nss_status _nss_oslogin_getpwuid_r(uid_t uid, struct passwd *result,
- char *buffer, size_t buflen,
- int *errnop) {
- BufferManager buffer_manager(buffer, buflen);
- std::stringstream url;
- url << kMetadataServerUrl << "users?uid=" << uid;
- string response;
- long http_code = 0;
- if (!HttpGet(url.str(), &response, &http_code) || http_code != 200 ||
- response.empty()) {
- *errnop = ENOENT;
- return NSS_STATUS_NOTFOUND;
- }
- if (!ParseJsonToPasswd(response, result, &buffer_manager, errnop)) {
- if (*errnop == EINVAL) {
- openlog("nss_oslogin", LOG_PID, LOG_USER);
- syslog(LOG_ERR, "Received malformed response from server: %s",
- response.c_str());
- closelog();
- }
- return *errnop == ERANGE ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
- }
- return NSS_STATUS_SUCCESS;
-}
-
-// Get a passwd entry by name.
-enum nss_status _nss_oslogin_getpwnam_r(const char *name, struct passwd *result,
- char *buffer, size_t buflen,
- int *errnop) {
- BufferManager buffer_manager(buffer, buflen);
- std::stringstream url;
- url << kMetadataServerUrl << "users?username=" << UrlEncode(name);
- string response;
- long http_code = 0;
- if (!HttpGet(url.str(), &response, &http_code) || http_code != 200 ||
- response.empty()) {
- *errnop = ENOENT;
- return NSS_STATUS_NOTFOUND;
- }
- if (!ParseJsonToPasswd(response, result, &buffer_manager, errnop)) {
- if (*errnop == EINVAL) {
- openlog("nss_oslogin", LOG_PID, LOG_USER);
- syslog(LOG_ERR, "Received malformed response from server: %s",
- response.c_str());
- closelog();
- }
- return *errnop == ERANGE ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
- }
- return NSS_STATUS_SUCCESS;
-}
-
-enum nss_status _nss_oslogin_getgrby(struct group *grp, char *buf,
- size_t buflen, int *errnop) {
- BufferManager buffer_manager(buf, buflen);
- if (!FindGroup(grp, &buffer_manager, errnop))
- return *errnop == ERANGE ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
-
- std::vector<string> users;
- if (!GetUsersForGroup(grp->gr_name, &users, errnop))
- return *errnop == ERANGE ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
-
- if (!AddUsersToGroup(users, grp, &buffer_manager, errnop))
- return *errnop == ERANGE ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
-
- return NSS_STATUS_SUCCESS;
-}
-
-enum nss_status _nss_oslogin_getgrgid_r(gid_t gid, struct group *grp, char *buf,
- size_t buflen, int *errnop) {
- grp->gr_gid = gid;
- return _nss_oslogin_getgrby(grp, buf, buflen, errnop);
-}
-
-enum nss_status _nss_oslogin_getgrnam_r(const char *name, struct group *grp,
- char *buf, size_t buflen, int *errnop) {
- grp->gr_name = (char *)name;
- return _nss_oslogin_getgrby(grp, buf, buflen, errnop);
-}
-
-enum nss_status _nss_oslogin_initgroups_dyn(const char *user, gid_t skipgroup,
- long int *start, long int *size,
- gid_t **groupsp, long int limit,
- int *errnop) {
- std::vector<Group> grouplist;
- if (!GetGroupsForUser(string(user), &grouplist, errnop)) {
- return NSS_STATUS_NOTFOUND;
- }
-
- gid_t *groups = *groupsp;
- for (int i = 0; i < (int) grouplist.size(); i++) {
- // Resize the buffer if needed.
- if (*start == *size) {
- gid_t *newgroups;
- long int newsize = 2 * *size;
- // Stop at limit if provided.
- if (limit > 0) {
- if (*size >= limit) {
- *errnop = ERANGE;
- return NSS_STATUS_TRYAGAIN;
- }
- newsize = MIN(limit, newsize);
- }
- newgroups = (gid_t *)realloc(groups, newsize * sizeof(gid_t *));
- if (newgroups == NULL) {
- *errnop = EAGAIN;
- return NSS_STATUS_TRYAGAIN;
- }
- *groupsp = groups = newgroups;
- *size = newsize;
- }
- groups[(*start)++] = grouplist[i].gid;
- }
- return NSS_STATUS_SUCCESS;
-}
-
-// nss_getpwent_r() is intentionally left unimplemented. This functionality is
-// now covered by the nss_cache binary and nss_cache module.
-
-nss_status _nss_oslogin_getpwent_r() { return NSS_STATUS_NOTFOUND; }
-nss_status _nss_oslogin_endpwent() { return NSS_STATUS_SUCCESS; }
-nss_status _nss_oslogin_setpwent() { return NSS_STATUS_SUCCESS; }
-
-NSS_METHOD_PROTOTYPE(__nss_compat_getpwnam_r);
-NSS_METHOD_PROTOTYPE(__nss_compat_getpwuid_r);
-NSS_METHOD_PROTOTYPE(__nss_compat_getpwent_r);
-NSS_METHOD_PROTOTYPE(__nss_compat_setpwent);
-NSS_METHOD_PROTOTYPE(__nss_compat_endpwent);
-NSS_METHOD_PROTOTYPE(__nss_compat_getgrnam_r);
-NSS_METHOD_PROTOTYPE(__nss_compat_getgrgid_r);
-
-DECLARE_NSS_METHOD_TABLE(methods,
- {NSDB_PASSWD, "getpwnam_r", __nss_compat_getpwnam_r,
- (void *)_nss_oslogin_getpwnam_r},
- {NSDB_PASSWD, "getpwuid_r", __nss_compat_getpwuid_r,
- (void *)_nss_oslogin_getpwuid_r},
- {NSDB_PASSWD, "getpwent_r", __nss_compat_getpwent_r,
- (void *)_nss_oslogin_getpwent_r},
- {NSDB_PASSWD, "endpwent", __nss_compat_endpwent,
- (void *)_nss_oslogin_endpwent},
- {NSDB_PASSWD, "setpwent", __nss_compat_setpwent,
- (void *)_nss_oslogin_setpwent},
- {NSDB_GROUP, "getgrnam_r", __nss_compat_getgrnam_r,
- (void *)_nss_oslogin_getgrnam_r},
- {NSDB_GROUP, "getgrgid_r", __nss_compat_getgrgid_r,
- (void *)_nss_oslogin_getgrgid_r}, )
-
-NSS_REGISTER_METHODS(methods)
-} // extern "C"
diff --git a/packages/google-compute-engine-oslogin/src/pam/pam_oslogin_admin.cc b/packages/google-compute-engine-oslogin/src/pam/pam_oslogin_admin.cc
deleted file mode 100644
index fe21db7..0000000
--- a/packages/google-compute-engine-oslogin/src/pam/pam_oslogin_admin.cc
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#define PAM_SM_ACCOUNT
-#include <security/pam_appl.h>
-#include <security/pam_modules.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#include <iostream>
-#include <fstream>
-#include <sstream>
-#include <string>
-
-#include <compat.h>
-#include <oslogin_utils.h>
-
-using std::string;
-
-using oslogin_utils::HttpGet;
-using oslogin_utils::GetUser;
-using oslogin_utils::kMetadataServerUrl;
-using oslogin_utils::ParseJsonToKey;
-using oslogin_utils::ParseJsonToEmail;
-using oslogin_utils::ParseJsonToSuccess;
-using oslogin_utils::UrlEncode;
-using oslogin_utils::ValidateUserName;
-
-static const char kSudoersDir[] = "/var/google-sudoers.d/";
-
-extern "C" {
-
-PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc,
- const char **argv) {
- // The return value for this module should generally be ignored. By default we
- // will return PAM_SUCCESS.
- int pam_result = PAM_SUCCESS;
- const char *user_name;
- if ((pam_result = pam_get_user(pamh, &user_name, NULL)) != PAM_SUCCESS) {
- PAM_SYSLOG(pamh, LOG_INFO, "Could not get pam user.");
- return pam_result;
- }
-
- if (!ValidateUserName(user_name)) {
- // If the user name is not a valid oslogin user, don't bother continuing.
- return PAM_SUCCESS;
- }
-
- string response;
- if (!GetUser(user_name, &response)) {
- return PAM_SUCCESS;
- }
-
- string email;
- if (!ParseJsonToEmail(response, &email) || email.empty()) {
- return PAM_SUCCESS;
- }
-
- std::stringstream url;
- url << kMetadataServerUrl << "authorize?email=" << UrlEncode(email)
- << "&policy=adminLogin";
-
- string filename = kSudoersDir;
- filename.append(user_name);
- struct stat buffer;
- bool file_exists = !stat(filename.c_str(), &buffer);
- long http_code;
- if (HttpGet(url.str(), &response, &http_code) && http_code == 200 &&
- ParseJsonToSuccess(response)) {
- if (!file_exists) {
- PAM_SYSLOG(pamh, LOG_INFO,
- "Granting sudo permissions to organization user %s.",
- user_name);
- std::ofstream sudoers_file;
- sudoers_file.open(filename.c_str());
- sudoers_file << user_name << " ALL=(ALL:ALL) NOPASSWD: ALL"
- << "\n";
- sudoers_file.close();
- chown(filename.c_str(), 0, 0);
- chmod(filename.c_str(), S_IRUSR | S_IRGRP);
- }
- } else if (file_exists) {
- remove(filename.c_str());
- }
- return pam_result;
-}
-}
diff --git a/packages/google-compute-engine-oslogin/src/pam/pam_oslogin_login.cc b/packages/google-compute-engine-oslogin/src/pam/pam_oslogin_login.cc
deleted file mode 100644
index 8ddec7b..0000000
--- a/packages/google-compute-engine-oslogin/src/pam/pam_oslogin_login.cc
+++ /dev/null
@@ -1,273 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#define PAM_SM_ACCOUNT
-#include <security/pam_appl.h>
-#include <security/pam_modules.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#include <iostream>
-#include <fstream>
-#include <sstream>
-#include <string>
-#include <map>
-
-#include <compat.h>
-#include <oslogin_utils.h>
-
-using oslogin_utils::ContinueSession;
-using oslogin_utils::GetUser;
-using oslogin_utils::HttpGet;
-using oslogin_utils::HttpPost;
-using oslogin_utils::kMetadataServerUrl;
-using oslogin_utils::ParseJsonToChallenges;
-using oslogin_utils::ParseJsonToKey;
-using oslogin_utils::ParseJsonToEmail;
-using oslogin_utils::ParseJsonToSuccess;
-using oslogin_utils::StartSession;
-using oslogin_utils::UrlEncode;
-using oslogin_utils::ValidateUserName;
-
-static const char kUsersDir[] = "/var/google-users.d/";
-
-extern "C" {
-PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc,
- const char **argv) {
- const char *user_name;
- if (pam_get_user(pamh, &user_name, NULL) != PAM_SUCCESS) {
- PAM_SYSLOG(pamh, LOG_INFO, "Could not get pam user.");
- return PAM_AUTH_ERR;
- }
-
- if (!ValidateUserName(user_name)) {
- // Not a valid OS Login username.
- return PAM_IGNORE;
- }
-
- std::string users_filename = kUsersDir;
- users_filename.append(user_name);
- struct stat buffer;
- bool file_exists = !stat(users_filename.c_str(), &buffer);
-
- std::string str_user_name(user_name);
- std::stringstream url;
- url << kMetadataServerUrl << "users?username=" << UrlEncode(str_user_name);
-
- std::string response;
- long http_code = 0;
- if (!HttpGet(url.str(), &response, &http_code) || response.empty() ||
- http_code != 200) {
- if (http_code == 404) {
- // This module is only consulted for OS Login users.
- return PAM_IGNORE;
- }
-
- // Check local file for that user as a last resort.
- if (file_exists) {
- return PAM_PERM_DENIED;
- }
-
- // We can't confirm this is an OS Login user, ignore module.
- return PAM_IGNORE;
- }
-
- std::string email;
- if (!ParseJsonToEmail(response, &email) || email.empty()) {
- return PAM_AUTH_ERR;
- }
-
- url.str("");
- url << kMetadataServerUrl << "authorize?email=" << UrlEncode(email)
- << "&policy=login";
- if (HttpGet(url.str(), &response, &http_code) && http_code == 200 &&
- ParseJsonToSuccess(response)) {
- if (!file_exists) {
- std::ofstream users_file(users_filename.c_str());
- chown(users_filename.c_str(), 0, 0);
- chmod(users_filename.c_str(), S_IRUSR | S_IWUSR | S_IRGRP);
- }
- PAM_SYSLOG(pamh, LOG_INFO,
- "Organization user %s has login permission.",
- user_name);
- return PAM_SUCCESS;
- } else {
- if (file_exists) {
- remove(users_filename.c_str());
- }
- PAM_SYSLOG(pamh, LOG_INFO,
- "Organization user %s does not have login permission.",
- user_name);
-
- return PAM_PERM_DENIED;
- }
-}
-
-PAM_EXTERN int pam_sm_setcred(pam_handle_t * pamh, int flags, int argc,
- const char **argv) {
- return PAM_SUCCESS;
-}
-
-PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags,
- int argc, const char **argv)
-{
- const char* user_name;
- if (pam_get_user(pamh, &user_name, NULL) != PAM_SUCCESS) {
- PAM_SYSLOG(pamh, LOG_INFO, "Could not get pam user.");
- return PAM_PERM_DENIED;
- }
-
- std::string str_user_name(user_name);
- if (!ValidateUserName(user_name)) {
- return PAM_PERM_DENIED;
- }
-
- std::string response;
- if (!(GetUser(str_user_name, &response))) {
- return PAM_PERM_DENIED;
- }
-
- // System accounts begin with the prefix `sa_`.
- std::string sa_prefix = "sa_";
- if (str_user_name.compare(0, sa_prefix.size(), sa_prefix) == 0) {
- return PAM_SUCCESS;
- }
-
- std::string email;
- if (!ParseJsonToEmail(response, &email) || email.empty()) {
- return PAM_PERM_DENIED;
- }
-
- response = "";
- if (!StartSession(email, &response)) {
- PAM_SYSLOG(pamh, LOG_ERR,
- "Bad response from the two-factor start session request: %s",
- response.empty() ? "empty response" : response.c_str());
- return PAM_PERM_DENIED;
- }
-
- std::string status;
- if (!ParseJsonToKey(response, "status", &status)) {
- PAM_SYSLOG(pamh, LOG_ERR,
- "Failed to parse status from start session response");
- return PAM_PERM_DENIED;
- }
-
- if (status == "NO_AVAILABLE_CHALLENGES") {
- return PAM_SUCCESS; // User is not two-factor enabled.
- }
-
- std::string session_id;
- if (!ParseJsonToKey(response, "sessionId", &session_id)) {
- return PAM_PERM_DENIED;
- }
-
- std::vector<oslogin_utils::Challenge> challenges;
- if (!ParseJsonToChallenges(response, &challenges)) {
- PAM_SYSLOG(pamh, LOG_ERR,
- "Failed to parse challenge values from JSON response");
- return PAM_PERM_DENIED;
- }
-
- std::map<std::string,std::string> user_prompts;
- user_prompts[AUTHZEN] = "Google phone prompt";
- user_prompts[TOTP] = "Security code from Google Authenticator application";
- user_prompts[INTERNAL_TWO_FACTOR] = "Security code from security key";
- user_prompts[IDV_PREREGISTERED_PHONE] =
- "Voice or text message verification code";
-
- oslogin_utils::Challenge challenge;
- if (challenges.size() > 1) {
- std::stringstream prompt;
- prompt << "Available authentication methods: ";
- for(vector<oslogin_utils::Challenge>::size_type i = 0;
- i != challenges.size(); ++i)
- prompt << "\n" << i+1 << ": " << user_prompts[challenges[i].type];
- prompt << "\n\nEnter a number: ";
-
- char *choice = NULL;
- if (pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &choice, "%s",
- prompt.str().c_str()) != PAM_SUCCESS) {
- pam_error(pamh, "Unable to get user input");
- }
-
- int choicei;
- if (sscanf(choice, "%d", &choicei) == EOF) {
- pam_error(pamh, "Unable to get user input");
- }
- if (choicei > challenges.size()) {
- pam_error(pamh, "Invalid option");
- }
- challenge = challenges[choicei - 1];
- } else {
- challenge = challenges[0];
- }
-
- if (challenge.status != "READY") {
- // Call continueSession with the START_ALTERNATE flag.
- if (!ContinueSession(true, email, "", session_id, challenge, &response)) {
- PAM_SYSLOG(pamh, LOG_ERR,
- "Bad response from two-factor continue session request: %s",
- response.empty() ? "empty response" : response.c_str());
- return PAM_PERM_DENIED;
- }
- }
-
- char* user_token = NULL;
- if (challenge.type == INTERNAL_TWO_FACTOR) {
- if (pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &user_token,
- "Enter your security code: ") != PAM_SUCCESS) {
- pam_error(pamh, "Unable to get user input");
- }
- } else if (challenge.type == TOTP) {
- if (pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &user_token,
- "Enter your one-time password: ") != PAM_SUCCESS) {
- pam_error(pamh, "Unable to get user input");
- }
- } else if (challenge.type == AUTHZEN) {
- if (pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &user_token,
- "A login prompt has been sent to your enrolled device. "
- "Press enter to continue") != PAM_SUCCESS) {
- pam_error(pamh, "Unable to get user input");
- }
- } else if (challenge.type == IDV_PREREGISTERED_PHONE) {
- if (pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &user_token,
- "A security code has been sent to your phone. "
- "Enter code to continue: ") != PAM_SUCCESS) {
- pam_error(pamh, "Unable to get user input");
- }
- } else {
- PAM_SYSLOG(pamh, LOG_ERR, "Unsupported challenge type %s",
- challenge.type.c_str());
- return PAM_PERM_DENIED;
- }
-
- if (!ContinueSession(false, email, user_token, session_id, challenge,
- &response)) {
- PAM_SYSLOG(pamh, LOG_ERR,
- "Bad response from two-factor continue session request: %s",
- response.empty() ? "empty response" : response.c_str());
- return PAM_PERM_DENIED;
- }
-
- if (!ParseJsonToKey(response, "status", &status)
- || status != "AUTHENTICATED") {
- return PAM_PERM_DENIED;
- }
-
- return PAM_SUCCESS;
-}
-}
diff --git a/packages/google-compute-engine-oslogin/src/utils.cc b/packages/google-compute-engine-oslogin/src/utils.cc
deleted file mode 100644
index 0f05f6f..0000000
--- a/packages/google-compute-engine-oslogin/src/utils.cc
+++ /dev/null
@@ -1,864 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Requires libcurl4-openssl-dev libjson0 and libjson0-dev
-#include <curl/curl.h>
-#include <errno.h>
-#include <grp.h>
-#include <json.h>
-#include <nss.h>
-#include <stdio.h>
-#include <time.h>
-
-#include <cstring>
-#include <iostream>
-#include <sstream>
-
-#if defined(__clang__) || __GNUC__ > 4 || \
- (__GNUC__ == 4 && \
- (__GNUC_MINOR__ > 9 || (__GNUC_MINOR__ == 9 && __GNUC_PATCHLEVEL__ > 0)))
-#include <regex>
-#define Regex std
-#else
-#include <boost/regex.hpp>
-#define Regex boost
-#endif
-
-#include <compat.h>
-#include <oslogin_utils.h>
-
-using std::string;
-
-// Maximum number of retries for HTTP requests.
-const int kMaxRetries = 1;
-
-// Regex for validating user names.
-const char kUserNameRegex[] = "^[a-zA-Z0-9._][a-zA-Z0-9._-]{0,31}$";
-
-namespace oslogin_utils {
-
-BufferManager::BufferManager(char* buf, size_t buflen)
- : buf_(buf), buflen_(buflen) {}
-
-bool BufferManager::AppendString(const string& value, char** buffer,
- int* errnop) {
- size_t bytes_to_write = value.length() + 1;
- *buffer = static_cast<char*>(Reserve(bytes_to_write, errnop));
- if (*buffer == NULL) {
- return false;
- }
- strncpy(*buffer, value.c_str(), bytes_to_write);
- return true;
-}
-
-bool BufferManager::CheckSpaceAvailable(size_t bytes_to_write) const {
- if (bytes_to_write > buflen_) {
- return false;
- }
- return true;
-}
-
-void* BufferManager::Reserve(size_t bytes, int* errnop) {
- if (!CheckSpaceAvailable(bytes)) {
- *errnop = ERANGE;
- return NULL;
- }
- void* result = buf_;
- buf_ += bytes;
- buflen_ -= bytes;
- return result;
-}
-
-NssCache::NssCache(int cache_size)
- : cache_size_(cache_size),
- passwd_cache_(cache_size),
- page_token_(""),
- on_last_page_(false) {}
-
-void NssCache::Reset() {
- page_token_ = "";
- index_ = 0;
- passwd_cache_.clear();
- on_last_page_ = false;
-}
-
-bool NssCache::HasNextPasswd() {
- return (index_ < passwd_cache_.size()) && !passwd_cache_[index_].empty();
-}
-
-bool NssCache::GetNextPasswd(BufferManager* buf, passwd* result, int* errnop) {
- if (!HasNextPasswd()) {
- *errnop = ENOENT;
- return false;
- }
- string cached_passwd = passwd_cache_[index_];
- bool success = ParseJsonToPasswd(cached_passwd, result, buf, errnop);
- if (success) {
- index_++;
- }
- return success;
-}
-
-bool NssCache::LoadJsonArrayToCache(string response) {
- Reset();
- json_object* root = NULL;
- root = json_tokener_parse(response.c_str());
- if (root == NULL) {
- return false;
- }
- // First grab the page token.
- json_object* page_token_object;
- if (json_object_object_get_ex(root, "nextPageToken", &page_token_object)) {
- page_token_ = json_object_get_string(page_token_object);
- } else {
- // If the page token is not found, assume something went wrong.
- page_token_ = "";
- on_last_page_ = true;
- return false;
- }
- // A page_token of 0 means we are done. This response will not contain any
- // login profiles.
- if (page_token_ == "0") {
- page_token_ = "";
- on_last_page_ = true;
- return false;
- }
- // Now grab all of the loginProfiles.
- json_object* login_profiles = NULL;
- if (!json_object_object_get_ex(root, "loginProfiles", &login_profiles)) {
- page_token_ = "";
- return false;
- }
- if (json_object_get_type(login_profiles) != json_type_array) {
- return false;
- }
- int arraylen = json_object_array_length(login_profiles);
- if (arraylen == 0 || arraylen > cache_size_) {
- page_token_ = "";
- return false;
- }
- for (int i = 0; i < arraylen; i++) {
- json_object* profile = json_object_array_get_idx(login_profiles, i);
- passwd_cache_.push_back(
- json_object_to_json_string_ext(profile, JSON_C_TO_STRING_PLAIN));
- }
- return true;
-}
-
-bool NssCache::NssGetpwentHelper(BufferManager* buf, struct passwd* result,
- int* errnop) {
- if (!HasNextPasswd() && !OnLastPage()) {
- std::stringstream url;
- url << kMetadataServerUrl << "users?pagesize=" << cache_size_;
- string page_token = GetPageToken();
- if (!page_token.empty()) {
- url << "&pagetoken=" << page_token;
- }
- string response;
- long http_code = 0;
- if (!HttpGet(url.str(), &response, &http_code) || http_code != 200 ||
- response.empty() || !LoadJsonArrayToCache(response)) {
- // It is possible this to be true after LoadJsonArrayToCache(), so we
- // must check it again.
- if (!OnLastPage()) {
- *errnop = ENOENT;
- }
- return false;
- }
- }
- if (HasNextPasswd() && !GetNextPasswd(buf, result, errnop)) {
- return false;
- }
- return true;
-}
-
-size_t OnCurlWrite(void* buf, size_t size, size_t nmemb, void* userp) {
- if (userp) {
- std::ostream& os = *static_cast<std::ostream*>(userp);
- std::streamsize len = size * nmemb;
- if (os.write(static_cast<char*>(buf), len)) {
- return len;
- }
- }
- return 0;
-}
-
-bool HttpDo(const string& url, const string& data, string* response,
- long* http_code) {
- if (response == NULL || http_code == NULL) {
- return false;
- }
- CURLcode code(CURLE_FAILED_INIT);
- curl_global_init(CURL_GLOBAL_ALL & ~CURL_GLOBAL_SSL);
- CURL* curl = curl_easy_init();
- std::ostringstream response_stream;
- int retry_count = 0;
- if (curl) {
- struct curl_slist* header_list = NULL;
- header_list = curl_slist_append(header_list, "Metadata-Flavor: Google");
- if (header_list == NULL) {
- curl_easy_cleanup(curl);
- curl_global_cleanup();
- return false;
- }
- do {
- response_stream.str("");
- response_stream.clear();
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &OnCurlWrite);
- curl_easy_setopt(curl, CURLOPT_FILE, &response_stream);
- curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5);
- curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
- if (data != "") {
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
- }
-
- code = curl_easy_perform(curl);
- if (code != CURLE_OK) {
- curl_easy_cleanup(curl);
- curl_global_cleanup();
- return false;
- }
- curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, http_code);
- } while (retry_count++ < kMaxRetries && *http_code == 500);
- curl_slist_free_all(header_list);
- }
- *response = response_stream.str();
- curl_easy_cleanup(curl);
- curl_global_cleanup();
- return true;
-}
-
-bool HttpGet(const string& url, string* response, long* http_code) {
- return HttpDo(url, "", response, http_code);
-}
-
-bool HttpPost(const string& url, const string& data, string* response,
- long* http_code) {
- return HttpDo(url, data, response, http_code);
-}
-
-bool ValidateUserName(const string& user_name) {
- Regex::regex r(kUserNameRegex);
- return Regex::regex_match(user_name, r);
-}
-
-string UrlEncode(const string& param) {
- CURL* curl = curl_easy_init();
- char* encoded = curl_easy_escape(curl, param.c_str(), param.length());
- if (encoded == NULL) {
- curl_easy_cleanup(curl);
- return "";
- }
- string encoded_param = encoded;
- curl_free(encoded);
- curl_easy_cleanup(curl);
- return encoded_param;
-}
-
-bool ValidatePasswd(struct passwd* result, BufferManager* buf, int* errnop) {
- // OS Login disallows uids less than 1000.
- if (result->pw_uid < 1000) {
- *errnop = EINVAL;
- return false;
- }
- if (result->pw_gid == 0) {
- *errnop = EINVAL;
- return false;
- }
- if (strlen(result->pw_name) == 0) {
- *errnop = EINVAL;
- return false;
- }
- if (strlen(result->pw_dir) == 0) {
- string home_dir = "/home/";
- home_dir.append(result->pw_name);
- if (!buf->AppendString(home_dir, &result->pw_dir, errnop)) {
- return false;
- }
- }
- if (strlen(result->pw_shell) == 0) {
- if (!buf->AppendString(DEFAULT_SHELL, &result->pw_shell, errnop)) {
- return false;
- }
- }
-
- // OS Login does not utilize the passwd field and reserves the gecos field.
- // Set these to be empty.
- if (!buf->AppendString("", &result->pw_gecos, errnop)) {
- return false;
- }
- if (!buf->AppendString("", &result->pw_passwd, errnop)) {
- return false;
- }
- return true;
-}
-
-bool ParseJsonToUsers(const string& json, std::vector<string>* result) {
- json_object* root = NULL;
- root = json_tokener_parse(json.c_str());
- if (root == NULL) {
- return false;
- }
-
- json_object* users = NULL;
- if (!json_object_object_get_ex(root, "usernames", &users)) {
- return false;
- }
- if (json_object_get_type(users) != json_type_array) {
- return false;
- }
- for (int idx = 0; idx < json_object_array_length(users); idx++) {
- json_object* user = json_object_array_get_idx(users, idx);
- const char* username = json_object_get_string(user);
- result->push_back(string(username));
- }
- return true;
-}
-
-bool ParseJsonToGroups(const string& json, std::vector<Group>* result) {
- json_object* root = NULL;
- root = json_tokener_parse(json.c_str());
- if (root == NULL) {
- return false;
- }
-
- json_object* groups = NULL;
- if (!json_object_object_get_ex(root, "posixGroups", &groups)) {
- return false;
- }
- if (json_object_get_type(groups) != json_type_array) {
- return false;
- }
- for (int idx = 0; idx < json_object_array_length(groups); idx++) {
- json_object* group = json_object_array_get_idx(groups, idx);
-
- json_object* gid;
- if (!json_object_object_get_ex(group, "gid", &gid)) {
- return false;
- }
-
- json_object* name;
- if (!json_object_object_get_ex(group, "name", &name)) {
- return false;
- }
-
- Group g;
- g.gid = json_object_get_int64(gid);
- // get_int64 will confusingly return 0 if the string can't be converted to
- // an integer. We can't rely on type check as it may be a string in the API.
- if (g.gid == 0) {
- return false;
- }
- g.name = json_object_get_string(name);
- if (g.name == "") {
- return false;
- }
-
- result->push_back(g);
- }
- return true;
-}
-
-std::vector<string> ParseJsonToSshKeys(const string& json) {
- std::vector<string> result;
- json_object* root = NULL;
- root = json_tokener_parse(json.c_str());
- if (root == NULL) {
- return result;
- }
- // Locate the sshPublicKeys object.
- json_object* login_profiles = NULL;
- if (!json_object_object_get_ex(root, "loginProfiles", &login_profiles)) {
- return result;
- }
- if (json_object_get_type(login_profiles) != json_type_array) {
- return result;
- }
- login_profiles = json_object_array_get_idx(login_profiles, 0);
-
- json_object* ssh_public_keys = NULL;
- if (!json_object_object_get_ex(login_profiles, "sshPublicKeys",
- &ssh_public_keys)) {
- return result;
- }
-
- if (json_object_get_type(ssh_public_keys) != json_type_object) {
- return result;
- }
- json_object_object_foreach(ssh_public_keys, key, obj) {
- (void)(key);
- if (json_object_get_type(obj) != json_type_object) {
- continue;
- }
- string key_to_add = "";
- bool expired = false;
- json_object_object_foreach(obj, key, val) {
- string string_key(key);
- int val_type = json_object_get_type(val);
- if (string_key == "key") {
- if (val_type != json_type_string) {
- continue;
- }
- key_to_add = (char*)json_object_get_string(val);
- }
- if (string_key == "expirationTimeUsec") {
- if (val_type == json_type_int || val_type == json_type_string) {
- uint64_t expiry_usec = (uint64_t)json_object_get_int64(val);
- struct timeval tp;
- gettimeofday(&tp, NULL);
- uint64_t cur_usec = tp.tv_sec * 1000000 + tp.tv_usec;
- expired = cur_usec > expiry_usec;
- } else {
- continue;
- }
- }
- }
- if (!key_to_add.empty() && !expired) {
- result.push_back(key_to_add);
- }
- }
- return result;
-}
-
-bool ParseJsonToPasswd(const string& json, struct passwd* result,
- BufferManager* buf, int* errnop) {
- json_object* root = NULL;
- root = json_tokener_parse(json.c_str());
- if (root == NULL) {
- *errnop = ENOENT;
- return false;
- }
- json_object* login_profiles = NULL;
- // If this is called from getpwent_r, loginProfiles won't be in the response.
- if (json_object_object_get_ex(root, "loginProfiles", &login_profiles)) {
- if (json_object_get_type(login_profiles) != json_type_array) {
- return false;
- }
- root = login_profiles;
- root = json_object_array_get_idx(root, 0);
- }
- // Locate the posixAccounts object.
- json_object* posix_accounts = NULL;
- if (!json_object_object_get_ex(root, "posixAccounts", &posix_accounts)) {
- *errnop = ENOENT;
- return false;
- }
- if (json_object_get_type(posix_accounts) != json_type_array) {
- return false;
- }
- posix_accounts = json_object_array_get_idx(posix_accounts, 0);
-
- // Populate with some default values that ValidatePasswd can detect if they
- // are not set.
- result->pw_uid = 0;
- result->pw_shell = (char*)"";
- result->pw_name = (char*)"";
- result->pw_dir = (char*)"";
-
- // Iterate through the json response and populate the passwd struct.
- if (json_object_get_type(posix_accounts) != json_type_object) {
- return false;
- }
- json_object_object_foreach(posix_accounts, key, val) {
- int val_type = json_object_get_type(val);
- // Convert char* to c++ string for easier comparison.
- string string_key(key);
-
- if (string_key == "uid") {
- if (val_type == json_type_int || val_type == json_type_string) {
- result->pw_uid = (uint32_t)json_object_get_int64(val);
- if (result->pw_uid == 0) {
- *errnop = EINVAL;
- return false;
- }
- } else {
- *errnop = EINVAL;
- return false;
- }
- } else if (string_key == "gid") {
- if (val_type == json_type_int || val_type == json_type_string) {
- result->pw_gid = (uint32_t)json_object_get_int64(val);
- // Use the uid as the default group when gid is not set or is zero.
- if (result->pw_gid == 0) {
- result->pw_gid = result->pw_uid;
- }
- } else {
- *errnop = EINVAL;
- return false;
- }
- } else if (string_key == "username") {
- if (val_type != json_type_string) {
- *errnop = EINVAL;
- return false;
- }
- if (!buf->AppendString((char*)json_object_get_string(val),
- &result->pw_name, errnop)) {
- return false;
- }
- } else if (string_key == "homeDirectory") {
- if (val_type != json_type_string) {
- *errnop = EINVAL;
- return false;
- }
- if (!buf->AppendString((char*)json_object_get_string(val),
- &result->pw_dir, errnop)) {
- return false;
- }
- } else if (string_key == "shell") {
- if (val_type != json_type_string) {
- *errnop = EINVAL;
- return false;
- }
- if (!buf->AppendString((char*)json_object_get_string(val),
- &result->pw_shell, errnop)) {
- return false;
- }
- }
- }
-
- return ValidatePasswd(result, buf, errnop);
-}
-
-bool AddUsersToGroup(std::vector<string> users, struct group* result,
- BufferManager* buf, int* errnop) {
- if (users.size() < 1) {
- return true;
- }
-
- // Get some space for the char* array for number of users + 1 for NULL cap.
- char** bufp;
- if (!(bufp =
- (char**)buf->Reserve(sizeof(char*) * (users.size() + 1), errnop))) {
- return false;
- }
- result->gr_mem = bufp;
-
- for (int i = 0; i < (int) users.size(); i++) {
- if (!buf->AppendString(users[i], bufp, errnop)) {
- result->gr_mem = NULL;
- return false;
- }
- }
- *bufp = NULL; // End the array with a null pointer.
-
- return true;
-}
-
-bool ParseJsonToEmail(const string& json, string* email) {
- json_object* root = NULL;
- root = json_tokener_parse(json.c_str());
- if (root == NULL) {
- return false;
- }
- // Locate the email object.
- json_object* login_profiles = NULL;
- if (!json_object_object_get_ex(root, "loginProfiles", &login_profiles)) {
- return false;
- }
- if (json_object_get_type(login_profiles) != json_type_array) {
- return false;
- }
- login_profiles = json_object_array_get_idx(login_profiles, 0);
- json_object* json_email = NULL;
- if (!json_object_object_get_ex(login_profiles, "name", &json_email)) {
- return false;
- }
-
- *email = json_object_get_string(json_email);
- return true;
-}
-
-bool ParseJsonToSuccess(const string& json) {
- json_object* root = NULL;
- root = json_tokener_parse(json.c_str());
- if (root == NULL) {
- return false;
- }
- json_object* success = NULL;
- if (!json_object_object_get_ex(root, "success", &success)) {
- return false;
- }
- return (bool)json_object_get_boolean(success);
-}
-
-bool ParseJsonToKey(const string& json, const string& key, string* response) {
- json_object* root = NULL;
- json_object* json_response = NULL;
- const char* c_response;
-
- root = json_tokener_parse(json.c_str());
- if (root == NULL) {
- return false;
- }
-
- if (!json_object_object_get_ex(root, key.c_str(), &json_response)) {
- return false;
- }
-
- if (!(c_response = json_object_get_string(json_response))) {
- return false;
- }
-
- *response = c_response;
- return true;
-}
-
-bool ParseJsonToChallenges(const string& json,
- std::vector<Challenge>* challenges) {
- json_object* root = NULL;
-
- root = json_tokener_parse(json.c_str());
- if (root == NULL) {
- return false;
- }
-
- json_object* jsonChallenges = NULL;
- if (!json_object_object_get_ex(root, "challenges", &jsonChallenges)) {
- return false;
- }
-
- json_object *challengeId, *challengeType, *challengeStatus = NULL;
- for (int i = 0; i < json_object_array_length(jsonChallenges); ++i) {
- if (!json_object_object_get_ex(json_object_array_get_idx(jsonChallenges, i),
- "challengeId", &challengeId)) {
- return false;
- }
- if (!json_object_object_get_ex(json_object_array_get_idx(jsonChallenges, i),
- "challengeType", &challengeType)) {
- return false;
- }
- if (!json_object_object_get_ex(json_object_array_get_idx(jsonChallenges, i),
- "status", &challengeStatus)) {
- return false;
- }
- Challenge challenge;
- challenge.id = json_object_get_int(challengeId);
- challenge.type = json_object_get_string(challengeType);
- challenge.status = json_object_get_string(challengeStatus);
-
- challenges->push_back(challenge);
- }
-
- return true;
-}
-
-bool FindGroup(struct group* result, BufferManager* buf, int* errnop) {
- if (result->gr_name == NULL && result->gr_gid == 0) {
- return false;
- }
- std::stringstream url;
- std::vector<Group> groups;
-
- string response;
- long http_code;
- string pageToken = "";
-
- do {
- url.str("");
- url << kMetadataServerUrl << "groups";
- if (pageToken != "") url << "?pageToken=" << pageToken;
-
- response.clear();
- http_code = 0;
- if (!HttpGet(url.str(), &response, &http_code) || http_code != 200 ||
- response.empty()) {
- *errnop = EAGAIN;
- return false;
- }
-
- if (!ParseJsonToKey(response, "nextPageToken", &pageToken)) {
- pageToken = "";
- }
-
- groups.clear();
- if (!ParseJsonToGroups(response, &groups) || groups.empty()) {
- *errnop = ENOENT;
- return false;
- }
-
- // Check for a match.
- for (int i = 0; i < (int) groups.size(); i++) {
- Group el = groups[i];
- if ((result->gr_name != NULL) && (string(result->gr_name) == el.name)) {
- // Set the name even though it matches because the final string must
- // be stored in the provided buffer.
- if (!buf->AppendString(el.name, &result->gr_name, errnop)) {
- return false;
- }
- result->gr_gid = el.gid;
- return true;
- }
- if ((result->gr_gid != 0) && (result->gr_gid == el.gid)) {
- if (!buf->AppendString(el.name, &result->gr_name, errnop)) {
- return false;
- }
- return true;
- }
- }
- } while (pageToken != "");
- // Not found.
- *errnop = ENOENT;
- return false;
-}
-
-bool GetGroupsForUser(string username, std::vector<Group>* groups,
- int* errnop) {
- std::stringstream url;
-
- string response;
- long http_code;
- string pageToken = "";
-
- do {
- url.str("");
- url << kMetadataServerUrl << "groups?username=" << username;
- if (pageToken != "") url << "?pageToken=" << pageToken;
-
- response.clear();
- http_code = 0;
- if (!HttpGet(url.str(), &response, &http_code) || http_code != 200 ||
- response.empty()) {
- *errnop = EAGAIN;
- return false;
- }
-
- if (!ParseJsonToKey(response, "pageToken", &pageToken)) {
- pageToken = "";
- }
-
- if (!ParseJsonToGroups(response, groups)) {
- *errnop = ENOENT;
- return false;
- }
- } while (pageToken != "");
- return true;
-}
-
-bool GetUsersForGroup(string groupname, std::vector<string>* users,
- int* errnop) {
- string response;
- long http_code;
- string pageToken = "";
- std::stringstream url;
-
- do {
- url.str("");
- url << kMetadataServerUrl << "users?groupname=" << groupname;
- if (pageToken != "") url << "?pageToken=" << pageToken;
-
- response.clear();
- http_code = 0;
- if (!HttpGet(url.str(), &response, &http_code) || http_code != 200 ||
- response.empty()) {
- *errnop = EAGAIN;
- return false;
- }
- if (!ParseJsonToKey(response, "nextPageToken", &pageToken)) {
- pageToken = "";
- }
- if (!ParseJsonToUsers(response, users)) {
- *errnop = EINVAL;
- return false;
- }
- } while (pageToken != "");
- return true;
-}
-
-bool GetUser(const string& username, string* response) {
- std::stringstream url;
- url << kMetadataServerUrl << "users?username=" << UrlEncode(username);
-
- long http_code = 0;
- if (!HttpGet(url.str(), response, &http_code) || response->empty() ||
- http_code != 200) {
- return false;
- }
- return true;
-}
-
-bool StartSession(const string& email, string* response) {
- bool ret = true;
- struct json_object *jobj, *jarr;
-
- jarr = json_object_new_array();
- json_object_array_add(jarr, json_object_new_string(INTERNAL_TWO_FACTOR));
- json_object_array_add(jarr, json_object_new_string(AUTHZEN));
- json_object_array_add(jarr, json_object_new_string(TOTP));
- json_object_array_add(jarr, json_object_new_string(IDV_PREREGISTERED_PHONE));
-
- jobj = json_object_new_object();
- json_object_object_add(jobj, "email", json_object_new_string(email.c_str()));
- json_object_object_add(jobj, "supportedChallengeTypes", jarr); // Ownership transferred to jobj.
-
- const char* data;
- data = json_object_to_json_string_ext(jobj, JSON_C_TO_STRING_PLAIN);
-
- std::stringstream url;
- url << kMetadataServerUrl << "authenticate/sessions/start";
-
- long http_code = 0;
- if (!HttpPost(url.str(), data, response, &http_code) || response->empty() ||
- http_code != 200) {
- ret = false;
- }
-
- json_object_put(jobj);
-
- return ret;
-}
-
-bool ContinueSession(bool alt, const string& email, const string& user_token,
- const string& session_id, const Challenge& challenge,
- string* response) {
- bool ret = true;
- struct json_object *jobj, *jresp;
-
- jobj = json_object_new_object();
- json_object_object_add(jobj, "email", json_object_new_string(email.c_str()));
- json_object_object_add(jobj, "challengeId",
- json_object_new_int(challenge.id));
-
- if (alt) {
- json_object_object_add(jobj, "action",
- json_object_new_string("START_ALTERNATE"));
- } else {
- json_object_object_add(jobj, "action", json_object_new_string("RESPOND"));
- }
-
- // AUTHZEN type and START_ALTERNATE action don't provide credentials.
- if (challenge.type != AUTHZEN && !alt) {
- jresp = json_object_new_object();
- json_object_object_add(jresp, "credential",
- json_object_new_string(user_token.c_str()));
- json_object_object_add(jobj, "proposalResponse", jresp); // Ownership transferred to jobj.
- }
-
- const char* data = NULL;
- data = json_object_to_json_string_ext(jobj, JSON_C_TO_STRING_PLAIN);
-
- std::stringstream url;
- url << kMetadataServerUrl << "authenticate/sessions/" << session_id
- << "/continue";
- long http_code = 0;
- if (!HttpPost(url.str(), data, response, &http_code) || response->empty() ||
- http_code != 200) {
- ret = false;
- }
-
- json_object_put(jobj);
-
- return ret;
-}
-} // namespace oslogin_utils
diff --git a/packages/google-compute-engine-oslogin/test/Makefile b/packages/google-compute-engine-oslogin/test/Makefile
deleted file mode 100644
index 83d23fd..0000000
--- a/packages/google-compute-engine-oslogin/test/Makefile
+++ /dev/null
@@ -1,34 +0,0 @@
-TOPDIR = $(realpath ..)
-
-CPPFLAGS += -I$(TOPDIR)/src/include -I/usr/include/json-c
-CXXFLAGS += -g -Wall -Wextra -std=c++11
-LDLIBS = -lcurl -ljson-c -lpthread
-
-all : test_runner non_network_tests
-
-clean :
- rm -f test_runner *.o
-
-gtest-all.o : $(GTEST_DIR)/src/gtest-all.cc
- $(CXX) $(CXXFLAGS) -isystem $(GTEST)/include -I$(GTEST) $(CPPFLAGS) -c $^
-
-test_runner : oslogin_utils_test.o $(TOPDIR)/src/utils.o gtest-all.o
- $(CXX) $(CXXFLAGS) $(CPPFLAGS) $^ -o $@ $(LDLIBS)
-
-non_network_tests : test_runner
- ./test_runner --gtest_filter=*-FindGroupTest.*:GetUsersForGroupTest.*
-
-network_tests : test_runner ping reset
- ./test_runner --gtest_filter=FindGroupTest.*:GetUsersForGroupTest.*
-
-# run as $ make tests GTESTARGS="--gtest_filter=FindGroupTest.*"
-tests : test_runner
- ./test_runner ${GTESTARGS}
-
-ping :
- nc -vzw2 metadata.google.internal 80 >/dev/null 2>&1
-
-reset :
- curl -Ss http://metadata.google.internal/reset >/dev/null 2>&1
-
-.PHONY : all clean tests ping reset gtest prowtest
diff --git a/packages/google-compute-engine-oslogin/test/oslogin_utils_test.cc b/packages/google-compute-engine-oslogin/test/oslogin_utils_test.cc
deleted file mode 100644
index 6c9c1df..0000000
--- a/packages/google-compute-engine-oslogin/test/oslogin_utils_test.cc
+++ /dev/null
@@ -1,627 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Requires libgtest-dev and gtest compiled and installed.
-#include <errno.h>
-#include <gtest/gtest.h>
-#include <oslogin_utils.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-using std::string;
-using std::vector;
-
-namespace oslogin_utils {
-
-// Test that the buffer can successfully append multiple strings.
-TEST(BufferManagerTest, TestAppendString) {
- size_t buflen = 20;
- char* buffer = (char*)malloc(buflen * sizeof(char));
- ASSERT_STRNE(buffer, NULL);
-
- char* first_string;
- char* second_string;
- int test_errno = 0;
- oslogin_utils::BufferManager buffer_manager(buffer, buflen);
- buffer_manager.AppendString("test1", &first_string, &test_errno);
- buffer_manager.AppendString("test2", &second_string, &test_errno);
- ASSERT_EQ(test_errno, 0);
- ASSERT_STREQ(first_string, "test1");
- ASSERT_STREQ(second_string, "test2");
- ASSERT_STREQ(buffer, "test1");
- ASSERT_STREQ((buffer + 6), "test2");
-}
-
-// Test that attempting to append a string larger than the buffer can handle
-// fails with ERANGE.
-TEST(BufferManagerTest, TestAppendStringTooLarge) {
- size_t buflen = 1;
- char* buffer = (char*)malloc(buflen * sizeof(char));
- ASSERT_STRNE(buffer, NULL);
-
- char* first_string;
- int test_errno = 0;
- oslogin_utils::BufferManager buffer_manager(buffer, buflen);
- ASSERT_FALSE(
- buffer_manager.AppendString("test1", &first_string, &test_errno));
- ASSERT_EQ(test_errno, ERANGE);
-}
-
-// Test successfully loading and retrieving an array of JSON posix accounts.
-TEST(NssCacheTest, TestLoadJsonArray) {
- NssCache nss_cache(2);
- string test_user1 =
- "{\"name\":\"foo@example.com\",\"posixAccounts\":["
- "{\"primary\":true,\"username\":\"foo\",\"uid\":1337,\"gid\":1337,"
- "\"homeDirectory\":\"/home/foo\",\"shell\":\"/bin/bash\"}]}";
- string test_user2 =
- "{\"name\":\"bar@example.com\","
- "\"posixAccounts\":["
- "{\"primary\":true,\"username\":\"bar\",\"uid\":1338,\"gid\":1338,"
- "\"homeDirectory\":\"/home/bar\",\"shell\":\"/bin/bash\"}]}";
- string response = "{\"loginProfiles\": [" + test_user1 + ", " + test_user2 +
- "], \"nextPageToken\": \"token\"}";
-
- ASSERT_TRUE(nss_cache.LoadJsonArrayToCache(response));
-
- size_t buflen = 500;
- char* buffer = (char*)malloc(buflen * sizeof(char));
- ASSERT_STRNE(buffer, NULL);
- BufferManager buf(buffer, buflen);
- struct passwd result;
- int test_errno = 0;
-
- // Verify that the first user was stored.
- ASSERT_TRUE(nss_cache.HasNextPasswd());
- ASSERT_TRUE(nss_cache.GetNextPasswd(&buf, &result, &test_errno));
- ASSERT_EQ(test_errno, 0);
- ASSERT_EQ(result.pw_uid, 1337);
- ASSERT_EQ(result.pw_gid, 1337);
- ASSERT_STREQ(result.pw_name, "foo");
- ASSERT_STREQ(result.pw_shell, "/bin/bash");
- ASSERT_STREQ(result.pw_dir, "/home/foo");
-
- // Verify that the second user was stored.
- ASSERT_TRUE(nss_cache.HasNextPasswd());
- ASSERT_TRUE(nss_cache.GetNextPasswd(&buf, &result, &test_errno));
- ASSERT_EQ(test_errno, 0);
- ASSERT_EQ(result.pw_uid, 1338);
- ASSERT_EQ(result.pw_gid, 1338);
- ASSERT_STREQ(result.pw_name, "bar");
- ASSERT_STREQ(result.pw_shell, "/bin/bash");
- ASSERT_STREQ(result.pw_dir, "/home/bar");
-
- // Verify that there are no more users stored.
- ASSERT_FALSE(nss_cache.HasNextPasswd());
- ASSERT_FALSE(nss_cache.GetNextPasswd(&buf, &result, &test_errno));
- ASSERT_EQ(test_errno, ENOENT);
-}
-
-// Test successfully loading and retrieving a partial array.
-TEST(NssCacheTest, TestLoadJsonPartialArray) {
- NssCache nss_cache(2);
- string test_user1 =
- "{\"name\":\"foo@example.com\",\"posixAccounts\":["
- "{\"primary\":true,\"username\":\"foo\",\"uid\":1337,\"gid\":1337,"
- "\"homeDirectory\":\"/home/foo\",\"shell\":\"/bin/bash\"}]}";
- string response =
- "{\"loginProfiles\": [" + test_user1 + "], \"nextPageToken\": \"token\"}";
-
- ASSERT_TRUE(nss_cache.LoadJsonArrayToCache(response));
-
- size_t buflen = 500;
- char* buffer = (char*)malloc(buflen * sizeof(char));
- ASSERT_STRNE(buffer, NULL);
- BufferManager buf(buffer, buflen);
- struct passwd result;
- int test_errno = 0;
-
- // Verify that the first user was stored.
- ASSERT_TRUE(nss_cache.HasNextPasswd());
- ASSERT_TRUE(nss_cache.GetNextPasswd(&buf, &result, &test_errno));
- ASSERT_EQ(test_errno, 0);
- ASSERT_EQ(result.pw_uid, 1337);
- ASSERT_EQ(result.pw_gid, 1337);
- ASSERT_STREQ(result.pw_name, "foo");
- ASSERT_STREQ(result.pw_shell, "/bin/bash");
- ASSERT_STREQ(result.pw_dir, "/home/foo");
-
- ASSERT_EQ(nss_cache.GetPageToken(), "token");
-
- // Verify that there are no more users stored.
- ASSERT_FALSE(nss_cache.HasNextPasswd());
- ASSERT_FALSE(nss_cache.GetNextPasswd(&buf, &result, &test_errno));
- ASSERT_EQ(test_errno, ENOENT);
-}
-
-// Test successfully loading and retrieving the final response.
-TEST(NssCacheTest, TestLoadJsonFinalResponse) {
- NssCache nss_cache(2);
- string response = "{\"nextPageToken\": \"0\"}";
-
- ASSERT_FALSE(nss_cache.LoadJsonArrayToCache(response));
- ASSERT_EQ(nss_cache.GetPageToken(), "");
-
- size_t buflen = 500;
- char* buffer = (char*)malloc(buflen * sizeof(char));
- ASSERT_STRNE(buffer, NULL);
- BufferManager buf(buffer, buflen);
- struct passwd result;
- int test_errno = 0;
-
- // Verify that there are no more users stored.
- ASSERT_FALSE(nss_cache.HasNextPasswd());
- ASSERT_TRUE(nss_cache.OnLastPage());
- ASSERT_FALSE(nss_cache.GetNextPasswd(&buf, &result, &test_errno));
- ASSERT_EQ(test_errno, ENOENT);
-}
-
-// Tests that resetting, and checking HasNextPasswd does not crash.
-TEST(NssCacheTest, ResetNullPtrTest) {
- NssCache nss_cache(2);
- nss_cache.Reset();
- ASSERT_FALSE(nss_cache.HasNextPasswd());
-}
-
-// Test parsing a valid JSON response from the metadata server.
-TEST(ParseJsonPasswdTest, ParseJsonToPasswdSucceeds) {
- string test_user =
- "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"posixAccounts\":["
- "{\"primary\":true,\"username\":\"foo\",\"uid\":1337,\"gid\":1338,"
- "\"homeDirectory\":\"/home/foo\",\"shell\":\"/bin/bash\"}]}]}";
-
- size_t buflen = 200;
- char* buffer = (char*)malloc(buflen * sizeof(char));
- ASSERT_STRNE(buffer, NULL);
- BufferManager buf(buffer, buflen);
- struct passwd result;
- int test_errno = 0;
- ASSERT_TRUE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno));
- ASSERT_EQ(result.pw_uid, 1337);
- ASSERT_EQ(result.pw_gid, 1338);
- ASSERT_STREQ(result.pw_name, "foo");
- ASSERT_STREQ(result.pw_shell, "/bin/bash");
- ASSERT_STREQ(result.pw_dir, "/home/foo");
-}
-
-// Test parsing a valid JSON response from the metadata server with uid > 2^31.
-TEST(ParseJsonPasswdTest, ParseJsonToPasswdSucceedsWithHighUid) {
- string test_user =
- "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"posixAccounts\":["
- "{\"primary\":true,\"username\":\"foo\",\"uid\":4294967295,\"gid\":"
- "4294967295,\"homeDirectory\":\"/home/foo\",\"shell\":\"/bin/bash\"}]}]}";
-
- size_t buflen = 200;
- char* buffer = (char*)malloc(buflen * sizeof(char));
- ASSERT_STRNE(buffer, NULL);
- BufferManager buf(buffer, buflen);
- struct passwd result;
- int test_errno = 0;
- ASSERT_TRUE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno));
- ASSERT_EQ(result.pw_uid, 4294967295);
- ASSERT_EQ(result.pw_gid, 4294967295);
- ASSERT_STREQ(result.pw_name, "foo");
- ASSERT_STREQ(result.pw_shell, "/bin/bash");
- ASSERT_STREQ(result.pw_dir, "/home/foo");
-}
-
-TEST(ParseJsonPasswdTest, ParseJsonToPasswdSucceedsWithStringUid) {
- string test_user =
- "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"posixAccounts\":["
- "{\"primary\":true,\"username\":\"foo\",\"uid\":\"1337\",\"gid\":"
- "\"1338\",\"homeDirectory\":\"/home/foo\",\"shell\":\"/bin/bash\"}]}]}";
-
- size_t buflen = 200;
- char* buffer = (char*)malloc(buflen * sizeof(char));
- ASSERT_STRNE(buffer, NULL);
- BufferManager buf(buffer, buflen);
- struct passwd result;
- int test_errno = 0;
- ASSERT_TRUE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno));
- ASSERT_EQ(result.pw_uid, 1337);
- ASSERT_EQ(result.pw_gid, 1338);
- ASSERT_STREQ(result.pw_name, "foo");
- ASSERT_STREQ(result.pw_shell, "/bin/bash");
- ASSERT_STREQ(result.pw_dir, "/home/foo");
-}
-
-TEST(ParseJsonPasswdTest, ParseJsonToPasswdNoLoginProfilesSucceeds) {
- string test_user =
- "{\"name\":\"foo@example.com\",\"posixAccounts\":["
- "{\"primary\":true,\"username\":\"foo\",\"uid\":1337,\"gid\":1337,"
- "\"homeDirectory\":\"/home/foo\",\"shell\":\"/bin/bash\"}]}";
-
- size_t buflen = 200;
- char* buffer = (char*)malloc(buflen * sizeof(char));
- ASSERT_STRNE(buffer, NULL);
- BufferManager buf(buffer, buflen);
- struct passwd result;
- int test_errno = 0;
- ASSERT_TRUE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno));
- ASSERT_EQ(result.pw_uid, 1337);
- ASSERT_EQ(result.pw_gid, 1337);
- ASSERT_STREQ(result.pw_name, "foo");
- ASSERT_STREQ(result.pw_shell, "/bin/bash");
- ASSERT_STREQ(result.pw_dir, "/home/foo");
-}
-
-// Test parsing a JSON response without enough space in the buffer.
-TEST(ParseJsonPasswdTest, ParseJsonToPasswdFailsWithERANGE) {
- string test_user =
- "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"posixAccounts\":["
- "{\"primary\":true,\"username\":\"foo\",\"uid\":1337,\"gid\":1337,"
- "\"homeDirectory\":\"/home/foo\",\"shell\":\"/bin/bash\"}]}]}";
-
- size_t buflen = 1;
- char* buffer = (char*)malloc(buflen * sizeof(char));
- ASSERT_STRNE(buffer, NULL);
- BufferManager buf(buffer, buflen);
- struct passwd result;
- int test_errno = 0;
- ASSERT_FALSE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno));
- ASSERT_EQ(test_errno, ERANGE);
-}
-
-// Test parsing malformed JSON responses.
-TEST(ParseJsonPasswdTest, ParseJsonToPasswdFailsWithEINVAL) {
- string test_user =
- "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"posixAccounts\":["
- "{\"primary\":true,\"username\":\"foo\",\"uid\": \"bad_stuff\""
- ",\"gid\":1337,\"homeDirectory\":\"/home/foo\","
- "\"shell\":\"/bin/bash\"}]}]}";
- string test_user2 =
- "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"posixAccounts\":["
- "{\"primary\":true,\"username\":\"foo\",\"uid\": 1337,"
- "\"gid\":\"bad_stuff\",\"homeDirectory\":\"/home/foo\","
- "\"shell\":\"/bin/bash\"}]}]}";
-
- size_t buflen = 200;
- char* buffer = (char*)malloc(buflen * sizeof(char));
- ASSERT_STRNE(buffer, NULL);
- BufferManager buf(buffer, buflen);
- struct passwd result;
- int test_errno = 0;
- ASSERT_FALSE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno));
- ASSERT_EQ(test_errno, EINVAL);
- // Reset errno.
- test_errno = 0;
- ASSERT_TRUE(ParseJsonToPasswd(test_user2, &result, &buf, &test_errno));
- ASSERT_EQ(test_errno, 0);
- ASSERT_EQ(result.pw_uid, 1337);
- ASSERT_EQ(result.pw_gid, 1337);
-}
-
-// Test parsing a partially filled response. Validate should fill empty fields
-// with default values.
-TEST(ParseJsonPasswdTest, ValidatePartialJsonResponse) {
- string test_user =
- "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"posixAccounts\":["
- "{\"primary\":true,\"username\":\"foo\",\"uid\":1337,\"gid\":1337}]"
- "}]}";
-
- size_t buflen = 200;
- char* buffer = (char*)malloc(buflen * sizeof(char));
- ASSERT_STRNE(buffer, NULL);
- BufferManager buf(buffer, buflen);
- struct passwd result;
- int test_errno = 0;
- ASSERT_TRUE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno));
- ASSERT_EQ(result.pw_uid, 1337);
- ASSERT_EQ(result.pw_gid, 1337);
- ASSERT_STREQ(result.pw_name, "foo");
- ASSERT_STREQ(result.pw_shell, "/bin/bash");
- ASSERT_STREQ(result.pw_dir, "/home/foo");
-}
-
-// Test parsing an invalid response. Validate should cause the parse to fail if
-// there is no uid.
-TEST(ParseJsonPasswdTest, ValidateInvalidJsonResponse) {
- string test_user =
- "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"posixAccounts\":["
- "{\"primary\":true,\"username\":\"foo\",\"gid\":1337}]"
- "}]}";
-
- size_t buflen = 200;
- char* buffer = (char*)malloc(buflen * sizeof(char));
- ASSERT_STRNE(buffer, NULL);
- BufferManager buf(buffer, buflen);
- struct passwd result;
- int test_errno = 0;
- ASSERT_FALSE(ParseJsonToPasswd(test_user, &result, &buf, &test_errno));
- ASSERT_EQ(test_errno, EINVAL);
-}
-
-// Test parsing a valid JSON response from the metadata server.
-TEST(ParseJsonToGroupsTest, ParseJsonToGroupsSucceeds) {
- string test_group = "{\"posixGroups\":[{\"name\":\"demo\",\"gid\":123452}]}";
-
- std::vector<Group> groups;
- ASSERT_TRUE(ParseJsonToGroups(test_group, &groups));
- ASSERT_EQ(groups[0].gid, 123452);
- ASSERT_EQ(groups[0].name, "demo");
-}
-
-// Test parsing a valid JSON response from the metadata server with gid > 2^31.
-TEST(ParseJsonToGroupsTest, ParseJsonToGroupsSucceedsWithHighGid) {
- string test_group =
- "{\"posixGroups\":[{\"name\":\"demo\",\"gid\":4294967295}]}";
-
- std::vector<Group> groups;
- ASSERT_TRUE(ParseJsonToGroups(test_group, &groups));
- ASSERT_EQ(groups[0].gid, 4294967295);
- ASSERT_EQ(groups[0].name, "demo");
-}
-
-TEST(ParseJsonToGroupsTest, ParseJsonToGroupsSucceedsWithStringGid) {
- string test_group =
- "{\"posixGroups\":[{\"name\":\"demo\",\"gid\":\"123452\"}]}";
-
- std::vector<Group> groups;
- ASSERT_TRUE(ParseJsonToGroups(test_group, &groups));
- ASSERT_EQ(groups[0].gid, 123452);
- ASSERT_EQ(groups[0].name, "demo");
-}
-
-// Test parsing malformed JSON responses.
-TEST(ParseJsonToGroupsTest, ParseJsonToGroupsFails) {
- string test_badgid =
- "{\"posixGroups\":[{\"name\":\"demo\",\"gid\":\"this-should-be-int\"}]}";
- string test_nogid = "{\"posixGroups\":[{\"name\":\"demo\"}]}";
- string test_noname = "{\"posixGroups\":[{\"gid\":123452}]}";
-
- std::vector<Group> groups;
- ASSERT_FALSE(ParseJsonToGroups(test_badgid, &groups));
- ASSERT_FALSE(ParseJsonToGroups(test_nogid, &groups));
- ASSERT_FALSE(ParseJsonToGroups(test_noname, &groups));
-}
-
-// Test parsing a valid JSON response from the metadata server.
-TEST(ParseJsonToUsersTest, ParseJsonToUsersSucceeds) {
- string test_group_users =
- "{\"usernames\":[\"user0001\",\"user0002\",\"user0003\",\"user0004\","
- "\"user0005\"]}";
-
- std::vector<string> users;
- ASSERT_TRUE(ParseJsonToUsers(test_group_users, &users));
- ASSERT_FALSE(users.empty());
- ASSERT_EQ(users.size(), 5);
-
- ASSERT_EQ(users[0], "user0001");
- ASSERT_EQ(users[1], "user0002");
- ASSERT_EQ(users[2], "user0003");
- ASSERT_EQ(users[3], "user0004");
- ASSERT_EQ(users[4], "user0005");
-}
-
-// Test parsing a valid JSON response from the metadata server.
-TEST(ParseJsonToUsersTest, ParseJsonToUsersEmptyGroupSucceeds) {
- string test_group_users = "{\"usernames\":[]}";
-
- std::vector<string> users;
- ASSERT_TRUE(ParseJsonToUsers(test_group_users, &users));
- ASSERT_TRUE(users.empty());
-}
-
-// Test parsing malformed JSON responses.
-TEST(ParseJsonToUsersTest, ParseJsonToUsersFails) {
- string test_group_users =
- "{\"badstuff\":[\"user0001\",\"user0002\",\"user0003\",\"user0004\","
- "\"user0005\"]}";
-
- std::vector<string> users;
- ASSERT_FALSE(ParseJsonToUsers(test_group_users, &users));
-}
-
-TEST(GetUsersForGroupTest, GetUsersForGroupSucceeds) {
- string response;
- long http_code;
- ASSERT_TRUE(
- HttpGet("http://metadata.google.internal/reset", &response, &http_code));
-
- std::vector<string> users;
- int errnop = 0;
-
- ASSERT_TRUE(GetUsersForGroup("demo", &users, &errnop));
- ASSERT_FALSE(users.empty());
- ASSERT_EQ(users[0], "user000173_grande_focustest_org");
- ASSERT_EQ(errnop, 0);
-}
-
-TEST(FindGroupTest, FindGroupByGidSucceeds) {
- string response;
- long http_code;
- ASSERT_TRUE(
- HttpGet("http://metadata.google.internal/reset", &response, &http_code));
-
- size_t buflen = 200 * sizeof(char);
- char* buffer = (char*)malloc(buflen);
- ASSERT_STRNE(buffer, NULL);
- BufferManager buf(buffer, buflen);
- int errnop = 0;
-
- struct group grp = {};
- grp.gr_gid = 123452;
- ASSERT_TRUE(FindGroup(&grp, &buf, &errnop));
- ASSERT_EQ(errnop, 0);
-}
-
-TEST(FindGroupTest, FindGroupByNameSucceeds) {
- string response;
- long http_code;
- ASSERT_TRUE(
- HttpGet("http://metadata.google.internal/reset", &response, &http_code));
-
- size_t buflen = 200 * sizeof(char);
- char* buffer = (char*)malloc(buflen);
- ASSERT_STRNE(buffer, NULL);
- BufferManager buf(buffer, buflen);
- int errnop;
-
- const char* match = "demo";
- struct group grp = {};
- grp.gr_name = (char*)match;
- ASSERT_TRUE(FindGroup(&grp, &buf, &errnop));
-}
-
-TEST(ParseJsonEmailTest, SuccessfullyParsesEmail) {
- string test_user =
- "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"posixAccounts\":["
- "{\"primary\":true,\"username\":\"foo\",\"gid\":1337}]"
- "}]}";
-
- string email;
- ASSERT_TRUE(ParseJsonToEmail(test_user, &email));
- ASSERT_EQ(email, "foo@example.com");
-}
-
-TEST(ParseJsonEmailTest, FailsParseEmail) {
- string email;
- ASSERT_FALSE(ParseJsonToEmail("random_junk", &email));
- ASSERT_EQ(email, "");
-}
-
-TEST(ParseJsonSshKeyTest, ParseJsonToSshKeysSucceeds) {
- string test_user =
- "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"sshPublicKeys\":"
- "{\"fingerprint\": {\"key\": \"test_key\"}}}]}";
-
- size_t buflen = 200;
- char* buffer = (char*)malloc(buflen * sizeof(char));
- ASSERT_STRNE(buffer, NULL);
- BufferManager buf(buffer, buflen);
- std::vector<string> result = ParseJsonToSshKeys(test_user);
- ASSERT_EQ(result.size(), 1);
- ASSERT_EQ(result[0], "test_key");
-}
-
-TEST(ParseJsonSshKeyTest, ParseJsonToSshKeysMultipleKeys) {
- string test_user =
- "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"sshPublicKeys\":"
- "{\"fingerprint\": {\"key\": \"test_key\"}, \"fingerprint2\": {\"key\": "
- "\"test_key2\"}}}]}";
-
- size_t buflen = 200;
- char* buffer = (char*)malloc(buflen * sizeof(char));
- ASSERT_STRNE(buffer, NULL);
- BufferManager buf(buffer, buflen);
- std::vector<string> result = ParseJsonToSshKeys(test_user);
- ASSERT_EQ(result.size(), 2);
- ASSERT_EQ(result[0], "test_key");
- ASSERT_EQ(result[1], "test_key2");
-}
-
-TEST(ParseJsonSshKeyTest, ParseJsonToSshKeysFiltersExpiredKeys) {
- string test_user =
- "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"sshPublicKeys\":"
- "{\"fingerprint\": {\"key\": \"test_key\"}, \"fingerprint2\": {\"key\": "
- "\"test_key2\", \"expirationTimeUsec\": 0}}}]}";
-
- size_t buflen = 200;
- char* buffer = (char*)malloc(buflen * sizeof(char));
- ASSERT_STRNE(buffer, NULL);
- BufferManager buf(buffer, buflen);
- std::vector<string> result = ParseJsonToSshKeys(test_user);
- ASSERT_EQ(result.size(), 1);
- ASSERT_EQ(result[0], "test_key");
-}
-
-TEST(ParseJsonSshKeyTest, ParseJsonToSshKeysFiltersMalformedExpiration) {
- string test_user =
- "{\"loginProfiles\":[{\"name\":\"foo@example.com\",\"sshPublicKeys\":"
- "{\"fingerprint\": {\"key\": \"test_key\"}, \"fingerprint2\": {\"key\": "
- "\"test_key2\", \"expirationTimeUsec\": \"bad_stuff\"}}}]}";
-
- size_t buflen = 200;
- char* buffer = (char*)malloc(buflen * sizeof(char));
- ASSERT_STRNE(buffer, NULL);
- BufferManager buf(buffer, buflen);
- std::vector<string> result = ParseJsonToSshKeys(test_user);
- ASSERT_EQ(result.size(), 1);
- ASSERT_EQ(result[0], "test_key");
-}
-
-TEST(ParseJsonAuthorizeSuccess, SuccessfullyAuthorized) {
- string response = "{\"success\": true}";
- ASSERT_TRUE(ParseJsonToSuccess(response));
-}
-
-TEST(ValidateUserNameTest, ValidateValidUserNames) {
- string cases[] = {"user", "_", ".", ".abc_",
- "_abc-", "ABC", "A_.-", "ausernamethirtytwocharacterslong"};
- for (auto test_user : cases) {
- ASSERT_TRUE(ValidateUserName(test_user));
- }
-}
-
-TEST(ValidateUserNameTest, ValidateInvalidUserNames) {
- string cases[] = {
- "",
- "!#$%^",
- "-abc",
- "#abc",
- "^abc",
- "abc*xyz",
- "abc xyz",
- "xyz*",
- "xyz$",
- "usernamethirtythreecharacterslong",
- "../../etc/shadow",
- };
- for (auto test_user : cases) {
- ASSERT_FALSE(ValidateUserName(test_user));
- }
-}
-
-TEST(ParseJsonKeyTest, TestKey) {
- string test_json = "{\"some_key\":\"some_value\"}";
- string value;
- ASSERT_TRUE(ParseJsonToKey(test_json, "some_key", &value));
- ASSERT_EQ(value, "some_value");
-}
-
-TEST(ParseJsonKeyTest, TestMissingKey) {
- string test_json = "{\"some_key\":\"some_value\"}";
- string value;
- ASSERT_FALSE(ParseJsonToKey(test_json, "some_other_key", &value));
- ASSERT_EQ(value, "");
-}
-
-TEST(ParseJsonChallengesTest, TestChallenges) {
- string challenges_json =
- "{\"status\":\"CHALLENGE_REQUIRED\",\"sessionId\":"
- "\"testSessionId\",\"challenges\":[{\"challengeId\":1,\"challengeType\":"
- "\"TOTP\",\"status\":\"READY\"}, {\"challengeId\":2,\"challengeType\":"
- "\"AUTHZEN\",\"status\":\"PROPOSED\"}]}";
- vector<Challenge> challenges;
- ASSERT_TRUE(ParseJsonToChallenges(challenges_json, &challenges));
- ASSERT_EQ(challenges.size(), 2);
- ASSERT_EQ(challenges[0].id, 1);
- ASSERT_EQ(challenges[0].type, "TOTP");
-}
-
-TEST(ParseJsonChallengesTest, TestMalformedChallenges) {
- string challenges_json =
- "{\"status\":\"CHALLENGE_REQUIRED\",\"sessionId\":"
- "\"testSessionId\",\"challenges\":[{\"challengeId\":1,\"challengeType\":"
- "\"TOTP\",\"status\":\"READY\"}, {\"challengeId\":2,\"challengeType\":"
- "\"AUTHZEN\"}]}";
- vector<Challenge> challenges;
- ASSERT_FALSE(ParseJsonToChallenges(challenges_json, &challenges));
- ASSERT_EQ(challenges.size(), 1);
-}
-} // namespace oslogin_utils
-int main(int argc, char** argv) {
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
diff --git a/packages/python-google-compute-engine/google_compute_engine/boto/boto_config.py b/packages/python-google-compute-engine/google_compute_engine/boto/boto_config.py
index 2c92d9d..4db24b4 100644
--- a/packages/python-google-compute-engine/google_compute_engine/boto/boto_config.py
+++ b/packages/python-google-compute-engine/google_compute_engine/boto/boto_config.py
@@ -58,14 +58,15 @@ class BotoConfig(object):
self.watcher = metadata_watcher.MetadataWatcher(logger=self.logger)
self._CreateConfig(project_id)
- def _GetNumericProjectId(self):
- """Get the numeric project ID for this VM.
+ def _GetProjectId(self):
+ """Get the (non-numeric) project ID for this VM.
Returns:
- string, the numeric project ID if one is found.
+ string, the project ID if one is found.
"""
- project_id = 'project/numeric-project-id'
- return self.watcher.GetMetadata(metadata_key=project_id, recursive=False)
+ project_id_key = 'project/project-id'
+ return self.watcher.GetMetadata(
+ metadata_key=project_id_key, recursive=False)
def _CreateConfig(self, project_id):
"""Create the boto config to support standalone GSUtil.
@@ -73,7 +74,7 @@ class BotoConfig(object):
Args:
project_id: string, the project ID to use in the config file.
"""
- project_id = project_id or self._GetNumericProjectId()
+ project_id = project_id or self._GetProjectId()
# Our project doesn't support service accounts.
if not project_id:
diff --git a/packages/python-google-compute-engine/google_compute_engine/boto/tests/boto_config_test.py b/packages/python-google-compute-engine/google_compute_engine/boto/tests/boto_config_test.py
index bc2c05a..1b57e19 100644
--- a/packages/python-google-compute-engine/google_compute_engine/boto/tests/boto_config_test.py
+++ b/packages/python-google-compute-engine/google_compute_engine/boto/tests/boto_config_test.py
@@ -68,7 +68,7 @@ class BotoConfigTest(unittest.TestCase):
boto_config.BotoConfig()
mock_watcher_instance.GetMetadata.assert_called_once_with(
- metadata_key='project/numeric-project-id', recursive=False)
+ metadata_key='project/project-id', recursive=False)
expected_calls = [
mock.call('GSUtil', 'default_project_id', self.project_id),
]
@@ -85,7 +85,7 @@ class BotoConfigTest(unittest.TestCase):
boto_config.BotoConfig()
mock_watcher_instance.GetMetadata.assert_called_once_with(
- metadata_key='project/numeric-project-id', recursive=False)
+ metadata_key='project/project-id', recursive=False)
mock_config.SetOption.assert_not_called()
diff --git a/packages/python-google-compute-engine/google_compute_engine/compat.py b/packages/python-google-compute-engine/google_compute_engine/compat.py
index 3d18c12..08bd0ed 100644
--- a/packages/python-google-compute-engine/google_compute_engine/compat.py
+++ b/packages/python-google-compute-engine/google_compute_engine/compat.py
@@ -48,12 +48,8 @@ elif 'red hat enterprise linux' in distro_name:
import google_compute_engine.distro_lib.el_7.utils as distro_utils
elif 'fedora' in distro_name:
import google_compute_engine.distro_lib.el_7.utils as distro_utils
-elif 'debian' in distro_name and distro_version == '8':
- import google_compute_engine.distro_lib.debian_8.utils as distro_utils
elif 'debian' in distro_name:
import google_compute_engine.distro_lib.debian_9.utils as distro_utils
-elif 'suse' in distro_name and distro_version == '11':
- import google_compute_engine.distro_lib.sles_11.utils as distro_utils
elif 'suse' in distro_name:
import google_compute_engine.distro_lib.sles_12.utils as distro_utils
elif 'freebsd' in distro_name:
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/__init__.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/__init__.py
+++ /dev/null
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/tests/__init__.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/tests/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/tests/__init__.py
+++ /dev/null
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/tests/utils_test.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/tests/utils_test.py
deleted file mode 100644
index 7f92795..0000000
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/tests/utils_test.py
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/usr/bin/python
-# Copyright 2018 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Unittest for utils.py module."""
-
-from google_compute_engine.distro_lib.debian_8 import utils
-from google_compute_engine.test_compat import mock
-from google_compute_engine.test_compat import unittest
-
-
-class UtilsTest(unittest.TestCase):
-
- def setUp(self):
- self.mock_logger = mock.Mock()
- self.mock_setup = mock.create_autospec(utils.Utils)
-
- @mock.patch('google_compute_engine.distro_lib.helpers.CallDhclientIpv6')
- @mock.patch('google_compute_engine.distro_lib.helpers.CallEnableRouteAdvertisements')
- def testEnableIpv6(self, mock_call_enable_ra, mock_call_dhclient):
- mocks = mock.Mock()
- mocks.attach_mock(mock_call_dhclient, 'dhclient')
- mocks.attach_mock(mock_call_enable_ra, 'enable_ra')
-
- utils.Utils.EnableIpv6(self.mock_setup, ['A', 'B'], self.mock_logger)
- expected_calls = [
- mock.call.enable_ra(['A', 'B'], mock.ANY),
- mock.call.dhclient(['A', 'B'], mock.ANY),
- ]
- self.assertEqual(mocks.mock_calls, expected_calls)
-
- @mock.patch('google_compute_engine.distro_lib.helpers.CallDhclientIpv6')
- def testDisableIpv6(self, mock_call_dhclient):
- mocks = mock.Mock()
- mocks.attach_mock(mock_call_dhclient, 'dhclient')
-
- utils.Utils.DisableIpv6(self.mock_setup, ['A', 'B'], self.mock_logger)
- expected_calls = [
- mock.call.dhclient(['A', 'B'], mock.ANY, None, release_lease=True),
- ]
- self.assertEqual(mocks.mock_calls, expected_calls)
-
- @mock.patch('google_compute_engine.distro_lib.helpers.CallDhclient')
- def testEnableNetworkInterfaces(self, mock_call):
- mocks = mock.Mock()
- mocks.attach_mock(mock_call, 'call')
-
- utils.Utils.EnableNetworkInterfaces(
- self.mock_setup, ['A', 'B'], self.mock_logger)
- expected_calls = [mock.call.call(['A', 'B'], mock.ANY)]
- self.assertEqual(mocks.mock_calls, expected_calls)
-
- @mock.patch('google_compute_engine.distro_lib.helpers.CallHwclock')
- def testHandleClockSync(self, mock_call):
- mocks = mock.Mock()
- mocks.attach_mock(mock_call, 'call')
-
- utils.Utils.HandleClockSync(self.mock_setup, self.mock_logger)
- expected_calls = [mock.call.call(mock.ANY)]
- self.assertEqual(mocks.mock_calls, expected_calls)
-
- @mock.patch('google_compute_engine.distro_lib.ip_forwarding_utils.IpForwardingUtilsIproute')
- def testIpForwardingUtils(self, mock_call):
- mocks = mock.Mock()
- mocks.attach_mock(mock_call, 'call')
-
- utils.Utils.IpForwardingUtils(self.mock_setup, self.mock_logger, '66')
- expected_calls = [mock.call.call(mock.ANY, '66')]
- self.assertEqual(mocks.mock_calls, expected_calls)
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/utils.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/utils.py
deleted file mode 100644
index 7872d1b..0000000
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/utils.py
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/python
-# Copyright 2018 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Utilities that are distro specific for use on Debian 8."""
-
-from google_compute_engine.distro_lib import helpers
-from google_compute_engine.distro_lib import ip_forwarding_utils
-from google_compute_engine.distro_lib import utils
-
-
-class Utils(utils.Utils):
- """Utilities used by Linux guest services on Debian 8."""
-
- def EnableIpv6(self, interfaces, logger, dhclient_script=None):
- """Configure the network interfaces for IPv6 using dhclient.
-
- Args:
- interface: string, the output device names for enabling IPv6.
- logger: logger object, used to write to SysLog and serial port.
- dhclient_script: string, the path to a dhclient script used by dhclient.
- """
- helpers.CallEnableRouteAdvertisements(interfaces, logger)
- helpers.CallDhclientIpv6(interfaces, logger)
-
- def DisableIpv6(self, interfaces, logger):
- """Disable Ipv6 by giving up the DHCP lease using dhclient.
-
- Args:
- interface: string, the output device names for enabling IPv6.
- logger: logger object, used to write to SysLog and serial port.
- """
- helpers.CallDhclientIpv6(interfaces, logger, None, release_lease=True)
-
- def EnableNetworkInterfaces(self, interfaces, logger, dhclient_script=None):
- """Enable the list of network interfaces.
-
- Args:
- interfaces: list of string, the output device names to enable.
- logger: logger object, used to write to SysLog and serial port.
- dhclient_script: string, the path to a dhclient script used by dhclient.
- """
- helpers.CallDhclient(interfaces, logger)
-
- def HandleClockSync(self, logger):
- """Sync the software clock with the hypervisor clock.
-
- Args:
- logger: logger object, used to write to SysLog and serial port.
- """
- helpers.CallHwclock(logger)
-
- def IpForwardingUtils(self, logger, proto_id=None):
- """Get system IP address configuration utilities.
-
- Args:
- logger: logger object, used to write to SysLog and serial port.
- proto_id: string, the routing protocol identifier for Google IP changes.
- """
- return ip_forwarding_utils.IpForwardingUtilsIproute(logger, proto_id)
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_9/utils.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_9/utils.py
index 9255214..2b12058 100644
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_9/utils.py
+++ b/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_9/utils.py
@@ -69,3 +69,11 @@ class Utils(utils.Utils):
proto_id: string, the routing protocol identifier for Google IP changes.
"""
return ip_forwarding_utils.IpForwardingUtilsIproute(logger, proto_id)
+
+ def RestartNetworking(self, logger):
+ """Restart the networking service to force a DHCP refresh.
+
+ Args:
+ logger: logger object, used to write to SysLog and serial port.
+ """
+ helpers.SystemctlRestart('networking', logger)
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_6/utils.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_6/utils.py
index 9f9bb98..a0fb839 100644
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_6/utils.py
+++ b/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_6/utils.py
@@ -15,6 +15,8 @@
"""Utilities that are distro specific for use on EL 6."""
+import subprocess
+
from google_compute_engine.distro_lib import helpers
from google_compute_engine.distro_lib import ip_forwarding_utils
from google_compute_engine.distro_lib import utils
@@ -70,3 +72,15 @@ class Utils(utils.Utils):
proto_id: string, the routing protocol identifier for Google IP changes.
"""
return ip_forwarding_utils.IpForwardingUtilsIproute(logger, proto_id)
+
+ def RestartNetworking(self, logger):
+ """Restart the networking service to force a DHCP refresh.
+
+ Args:
+ logger: logger object, used to write to SysLog and serial port.
+ """
+ logger.info('Restarting networking via "service network restart".')
+ try:
+ subprocess.check_call(['service', 'network', 'restart'])
+ except subprocess.CalledProcessError:
+ logger.warning('Failed to restart networking.')
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_7/utils.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_7/utils.py
index e0e318b..8b82aef 100644
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_7/utils.py
+++ b/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_7/utils.py
@@ -127,3 +127,11 @@ class Utils(utils.Utils):
proto_id: string, the routing protocol identifier for Google IP changes.
"""
return ip_forwarding_utils.IpForwardingUtilsIproute(logger, proto_id)
+
+ def RestartNetworking(self, logger):
+ """Restart the networking service to force a DHCP refresh.
+
+ Args:
+ logger: logger object, used to write to SysLog and serial port.
+ """
+ helpers.SystemctlRestart('NetworkManager', logger)
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/freebsd_11/utils.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/freebsd_11/utils.py
index 2734c8f..121cad7 100644
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/freebsd_11/utils.py
+++ b/packages/python-google-compute-engine/google_compute_engine/distro_lib/freebsd_11/utils.py
@@ -59,3 +59,11 @@ class Utils(utils.Utils):
proto_id: string, the routing protocol identifier for Google IP changes.
"""
return ip_forwarding_utils.IpForwardingUtilsIfconfig(logger)
+
+ def RestartNetworking(self, logger):
+ """Restart the networking service to force a DHCP refresh.
+
+ Args:
+ logger: logger object, used to write to SysLog and serial port.
+ """
+ pass
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/helpers.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/helpers.py
index b7d16a1..a0be6a0 100644
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/helpers.py
+++ b/packages/python-google-compute-engine/google_compute_engine/distro_lib/helpers.py
@@ -80,6 +80,7 @@ def CallDhclientIpv6(interfaces, logger, dhclient_script=None,
def CallEnableRouteAdvertisements(interfaces, logger):
"""Enable route advertisements.
+
Args:
interfaces: list of string, the output device names to enable.
logger: logger object, used to write to SysLog and serial port.
@@ -140,3 +141,17 @@ def CallSysctl(logger, name, value):
subprocess.check_call(sysctl_command)
except subprocess.CalledProcessError:
logger.warning('Unable to configure sysctl %s.', name)
+
+def SystemctlRestart(service, logger):
+ """Restart a service using systemctl.
+
+ Args:
+ service: the name of the service to restart.
+ logger: logger object, used to write to SysLog and serial port.
+ """
+ logger.info('Restarting service via "systemctl restart %s".', service)
+ systemctl_command = ['systemctl', 'restart', service]
+ try:
+ subprocess.check_call(systemctl_command)
+ except subprocess.CalledProcessError:
+ logger.warning('Failed to restart service %s.', service)
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/sles_11/__init__.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/sles_11/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/sles_11/__init__.py
+++ /dev/null
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/sles_11/tests/__init__.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/sles_11/tests/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/sles_11/tests/__init__.py
+++ /dev/null
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/sles_11/tests/utils_test.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/sles_11/tests/utils_test.py
deleted file mode 100644
index 22d54de..0000000
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/sles_11/tests/utils_test.py
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/usr/bin/python
-# Copyright 2018 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Unittest for utils.py module."""
-
-import subprocess
-
-from google_compute_engine.distro_lib.sles_11 import utils
-from google_compute_engine.test_compat import mock
-from google_compute_engine.test_compat import unittest
-
-
-class UtilsTest(unittest.TestCase):
-
- def setUp(self):
- self.mock_logger = mock.Mock()
- self.mock_setup = mock.create_autospec(utils.Utils)
-
- def testEnableNetworkInterfacesWithSingleNic(self):
- mocks = mock.Mock()
-
- utils.Utils.EnableNetworkInterfaces(
- self.mock_setup, ['eth0'], self.mock_logger)
- expected_calls = []
- self.assertEqual(mocks.mock_calls, expected_calls)
-
- def testEnableNetworkInterfacesWithMultipleNics(self):
- mocks = mock.Mock()
- mocks.attach_mock(self.mock_setup._Dhcpcd, 'dhcpcd')
-
- utils.Utils.EnableNetworkInterfaces(
- self.mock_setup, ['eth0', 'eth1', 'eth2'], self.mock_logger)
- expected_calls = [
- mock.call.dhcpcd(['eth1', 'eth2'], mock.ANY),
- ]
- self.assertEqual(mocks.mock_calls, expected_calls)
-
- @mock.patch(
- 'google_compute_engine.distro_lib.sles_11.utils.subprocess.check_call')
- def testDhcpcd(self, mock_call):
- mocks = mock.Mock()
- mocks.attach_mock(mock_call, 'call')
- mocks.attach_mock(self.mock_logger, 'logger')
- mock_call.side_effect = [
- None, None, None, None,
- subprocess.CalledProcessError(1, 'Test'),
- subprocess.CalledProcessError(1, 'Test'),
- ]
-
- utils.Utils._Dhcpcd(
- self.mock_setup, ['eth1', 'eth2', 'eth3'], self.mock_logger)
- expected_calls = [
- mock.call.call(['/sbin/dhcpcd', '-x', 'eth1']),
- mock.call.call(['/sbin/dhcpcd', 'eth1']),
- mock.call.call(['/sbin/dhcpcd', '-x', 'eth2']),
- mock.call.call(['/sbin/dhcpcd', 'eth2']),
- mock.call.call(['/sbin/dhcpcd', '-x', 'eth3']),
- mock.call.logger.info(mock.ANY, 'eth3'),
- mock.call.call(['/sbin/dhcpcd','eth3']),
- mock.call.logger.warning(mock.ANY, 'eth3'),
- ]
- self.assertEqual(mocks.mock_calls, expected_calls)
-
- @mock.patch('google_compute_engine.distro_lib.helpers.CallHwclock')
- def testHandleClockSync(self, mock_call):
- mocks = mock.Mock()
- mocks.attach_mock(mock_call, 'call')
-
- utils.Utils.HandleClockSync(self.mock_setup, self.mock_logger)
- expected_calls = [mock.call.call(mock.ANY)]
- self.assertEqual(mocks.mock_calls, expected_calls)
-
- @mock.patch('google_compute_engine.distro_lib.ip_forwarding_utils.IpForwardingUtilsIproute')
- def testIpForwardingUtils(self, mock_call):
- mocks = mock.Mock()
- mocks.attach_mock(mock_call, 'call')
-
- utils.Utils.IpForwardingUtils(self.mock_setup, self.mock_logger, '66')
- expected_calls = [mock.call.call(mock.ANY, '66')]
- self.assertEqual(mocks.mock_calls, expected_calls)
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/sles_11/utils.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/sles_11/utils.py
deleted file mode 100644
index 623505c..0000000
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/sles_11/utils.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/usr/bin/python
-# Copyright 2018 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Utilities that are distro specific for use on SUSE 11."""
-
-import os
-import subprocess
-
-from google_compute_engine import constants
-from google_compute_engine.distro_lib import helpers
-from google_compute_engine.distro_lib import ip_forwarding_utils
-from google_compute_engine.distro_lib import utils
-
-
-class Utils(utils.Utils):
- """Utilities used by Linux guest services on SUSE 11."""
-
- def EnableIpv6(self, interfaces, logger, dhclient_script=None):
- """Configure the network interfaces for IPv6 using dhclient.
-
- Args:
- interface: string, the output device names for enabling IPv6.
- logger: logger object, used to write to SysLog and serial port.
- dhclient_script: string, the path to a dhclient script used by dhclient.
- """
- pass
-
- def EnableNetworkInterfaces(self, interfaces, logger, dhclient_script=None):
- """Enable the list of network interfaces.
-
- Args:
- interfaces: list of string, the output device names to enable.
- logger: logger object, used to write to SysLog and serial port.
- dhclient_script: string, the path to a dhclient script used by dhclient.
- """
- interfaces_to_up = [i for i in interfaces if i != 'eth0']
- if interfaces_to_up:
- logger.info('Enabling the Ethernet interfaces %s.', interfaces_to_up)
- self._Dhcpcd(interfaces_to_up, logger)
-
- def _Dhcpcd(self, interfaces, logger):
- """Use dhcpcd to activate the interfaces.
-
- Args:
- interfaces: list of string, the output device names to enable.
- logger: logger object, used to write to SysLog and serial port.
- """
- for interface in interfaces:
- dhcpcd = ['/sbin/dhcpcd']
- try:
- subprocess.check_call(dhcpcd + ['-x', interface])
- except subprocess.CalledProcessError:
- # Dhcpcd not yet running for this device.
- logger.info('Dhcpcd not yet running for interface %s.', interface)
- try:
- subprocess.check_call(dhcpcd + [interface])
- except subprocess.CalledProcessError:
- # The interface is already active.
- logger.warning('Could not activate interface %s.', interface)
-
- def HandleClockSync(self, logger):
- """Sync the software clock with the hypervisor clock.
-
- Args:
- logger: logger object, used to write to SysLog and serial port.
- """
- helpers.CallHwclock(logger)
-
- def IpForwardingUtils(self, logger, proto_id=None):
- """Get system IP address configuration utilities.
-
- Args:
- logger: logger object, used to write to SysLog and serial port.
- proto_id: string, the routing protocol identifier for Google IP changes.
- """
- return ip_forwarding_utils.IpForwardingUtilsIproute(logger, proto_id)
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/sles_12/utils.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/sles_12/utils.py
index b4a3d00..a8bd486 100644
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/sles_12/utils.py
+++ b/packages/python-google-compute-engine/google_compute_engine/distro_lib/sles_12/utils.py
@@ -108,3 +108,11 @@ class Utils(utils.Utils):
proto_id: string, the routing protocol identifier for Google IP changes.
"""
return ip_forwarding_utils.IpForwardingUtilsIproute(logger, proto_id)
+
+ def RestartNetworking(self, logger):
+ """Restart the networking service to force a DHCP refresh.
+
+ Args:
+ logger: logger object, used to write to SysLog and serial port.
+ """
+ helpers.SystemctlRestart('wickedd-nanny', logger)
diff --git a/packages/python-google-compute-engine/google_compute_engine/networking/network_daemon.py b/packages/python-google-compute-engine/google_compute_engine/networking/network_daemon.py
index e152464..5a791cc 100644
--- a/packages/python-google-compute-engine/google_compute_engine/networking/network_daemon.py
+++ b/packages/python-google-compute-engine/google_compute_engine/networking/network_daemon.py
@@ -22,6 +22,7 @@ Update IP forwarding when metadata changes.
import logging.handlers
import optparse
import random
+import socket
from google_compute_engine import config_manager
from google_compute_engine import constants
@@ -29,6 +30,7 @@ from google_compute_engine import file_utils
from google_compute_engine import logger
from google_compute_engine import metadata_watcher
from google_compute_engine import network_utils
+from google_compute_engine.compat import distro_utils
from google_compute_engine.networking.ip_forwarding import ip_forwarding
from google_compute_engine.networking.network_setup import network_setup
@@ -38,7 +40,7 @@ LOCKFILE = constants.LOCALSTATEDIR + '/lock/google_networking.lock'
class NetworkDaemon(object):
"""Manage networking based on changes to network metadata."""
- network_interface_metadata_key = 'instance/network-interfaces'
+ instance_metadata_key = 'instance/'
def __init__(
self, ip_forwarding_enabled, proto_id, ip_aliases, target_instance_ips,
@@ -62,6 +64,7 @@ class NetworkDaemon(object):
self.ip_forwarding_enabled = ip_forwarding_enabled
self.network_setup_enabled = network_setup_enabled
self.target_instance_ips = target_instance_ips
+ self.dhclient_script = dhclient_script
self.ip_forwarding = ip_forwarding.IpForwarding(
proto_id=proto_id, debug=debug)
@@ -69,6 +72,7 @@ class NetworkDaemon(object):
dhclient_script=dhclient_script, dhcp_command=dhcp_command, debug=debug)
self.network_utils = network_utils.NetworkUtils(logger=self.logger)
self.watcher = metadata_watcher.MetadataWatcher(logger=self.logger)
+ self.distro_utils = distro_utils.Utils(debug=debug)
try:
with file_utils.LockFile(LOCKFILE):
@@ -76,7 +80,7 @@ class NetworkDaemon(object):
timeout = 60 + random.randint(0, 30)
self.watcher.WatchMetadata(
self.HandleNetworkInterfaces,
- metadata_key=self.network_interface_metadata_key, recursive=True,
+ metadata_key=self.instance_metadata_key, recursive=True,
timeout=timeout)
except (IOError, OSError) as e:
self.logger.warning(str(e))
@@ -87,7 +91,8 @@ class NetworkDaemon(object):
Args:
result: dict, the metadata response with the network interfaces.
"""
- network_interfaces = self._ExtractInterfaceMetadata(result)
+ network_interfaces = self._ExtractInterfaceMetadata(
+ result['networkInterfaces'])
if self.network_setup_enabled:
default_interface = network_interfaces[0]
@@ -98,10 +103,12 @@ class NetworkDaemon(object):
self.network_setup.EnableNetworkInterfaces(
[interface.name for interface in network_interfaces[1:]])
- for interface in network_interfaces:
- if self.ip_forwarding_enabled:
+ if self.ip_forwarding_enabled:
+ for interface in network_interfaces:
self.ip_forwarding.HandleForwardedIps(
interface.name, interface.forwarded_ips, interface.ip)
+ if socket.gethostname() != result['hostname'].split('.')[0]:
+ self.distro_utils.RestartNetworking(self.logger)
def _ExtractInterfaceMetadata(self, metadata):
"""Extracts network interface metadata.
diff --git a/packages/python-google-compute-engine/google_compute_engine/networking/tests/network_daemon_test.py b/packages/python-google-compute-engine/google_compute_engine/networking/tests/network_daemon_test.py
index 9216ea3..2c3640a 100644
--- a/packages/python-google-compute-engine/google_compute_engine/networking/tests/network_daemon_test.py
+++ b/packages/python-google-compute-engine/google_compute_engine/networking/tests/network_daemon_test.py
@@ -54,7 +54,7 @@ class NetworkDaemonTest(unittest.TestCase):
mocks.attach_mock(mock_ip_forwarding, 'forwarding')
mocks.attach_mock(mock_network_setup, 'network_setup')
mocks.attach_mock(mock_watcher, 'watcher')
- metadata_key = network_daemon.NetworkDaemon.network_interface_metadata_key
+ metadata_key = network_daemon.NetworkDaemon.instance_metadata_key
with mock.patch.object(
network_daemon.NetworkDaemon, 'HandleNetworkInterfaces'
@@ -129,11 +129,13 @@ class NetworkDaemonTest(unittest.TestCase):
]
self.assertEqual(mocks.mock_calls, expected_calls)
- def testHandleNetworkInterfaces(self):
+ @mock.patch('google_compute_engine.networking.network_daemon.distro_utils')
+ def testHandleNetworkInterfaces(self, mock_distro_utils):
mocks = mock.Mock()
mocks.attach_mock(self.mock_ip_forwarding, 'forwarding')
mocks.attach_mock(self.mock_network_setup, 'network_setup')
mocks.attach_mock(self.mock_setup, 'setup')
+ mocks.attach_mock(mock_distro_utils, 'distro_utils')
self.mock_setup.ip_aliases = None
self.mock_setup.target_instance_ips = None
self.mock_setup.ip_forwarding_enabled = True
@@ -143,17 +145,19 @@ class NetworkDaemonTest(unittest.TestCase):
'eth0', forwarded_ips=['a'], ip='1.1.1.1', ipv6=False),
network_daemon.NetworkDaemon.NetworkInterface('eth1'),
]
- result = mock.Mock()
+ self.mock_setup.distro_utils = mock.MagicMock()
+ result = mock.MagicMock()
network_daemon.NetworkDaemon.HandleNetworkInterfaces(
self.mock_setup, result)
expected_calls = [
- mock.call.setup._ExtractInterfaceMetadata(result),
+ mock.call.setup._ExtractInterfaceMetadata(result['networkInterfaces']),
mock.call.network_setup.DisableIpv6(['eth0']),
mock.call.network_setup.EnableNetworkInterfaces(['eth1']),
mock.call.forwarding.HandleForwardedIps(
'eth0', ['a'], '1.1.1.1'),
mock.call.forwarding.HandleForwardedIps('eth1', None, None),
+ mock.call.setup.distro_utils.RestartNetworking(self.mock_setup.logger),
]
self.assertEqual(mocks.mock_calls, expected_calls)
@@ -170,16 +174,18 @@ class NetworkDaemonTest(unittest.TestCase):
network_daemon.NetworkDaemon.NetworkInterface(
'eth0', forwarded_ips=['a'], ip='1.1.1.1', ipv6=True),
]
- result = mock.Mock()
+ self.mock_setup.distro_utils = mock.MagicMock()
+ result = mock.MagicMock()
network_daemon.NetworkDaemon.HandleNetworkInterfaces(
self.mock_setup, result)
expected_calls = [
- mock.call.setup._ExtractInterfaceMetadata(result),
+ mock.call.setup._ExtractInterfaceMetadata(result['networkInterfaces']),
mock.call.network_setup.EnableIpv6(['eth0']),
mock.call.network_setup.EnableNetworkInterfaces([]),
mock.call.forwarding.HandleForwardedIps(
'eth0', ['a'], '1.1.1.1'),
+ mock.call.setup.distro_utils.RestartNetworking(self.mock_setup.logger),
]
self.assertEqual(mocks.mock_calls, expected_calls)
@@ -196,16 +202,18 @@ class NetworkDaemonTest(unittest.TestCase):
network_daemon.NetworkDaemon.NetworkInterface(
'eth0', forwarded_ips=['a'], ip='1.1.1.1', ipv6=False),
]
- result = mock.Mock()
+ self.mock_setup.distro_utils = mock.MagicMock()
+ result = mock.MagicMock()
network_daemon.NetworkDaemon.HandleNetworkInterfaces(
self.mock_setup, result)
expected_calls = [
- mock.call.setup._ExtractInterfaceMetadata(result),
+ mock.call.setup._ExtractInterfaceMetadata(result['networkInterfaces']),
mock.call.network_setup.DisableIpv6(['eth0']),
mock.call.network_setup.EnableNetworkInterfaces([]),
mock.call.forwarding.HandleForwardedIps(
'eth0', ['a'], '1.1.1.1'),
+ mock.call.setup.distro_utils.RestartNetworking(self.mock_setup.logger),
]
self.assertEqual(mocks.mock_calls, expected_calls)
@@ -222,12 +230,14 @@ class NetworkDaemonTest(unittest.TestCase):
network_daemon.NetworkDaemon.NetworkInterface('a'),
network_daemon.NetworkDaemon.NetworkInterface('b'),
]
- result = mock.Mock()
+ self.mock_setup.distro_utils = mock.MagicMock()
+ result = mock.MagicMock()
network_daemon.NetworkDaemon.HandleNetworkInterfaces(
self.mock_setup, result)
expected_calls = [
- mock.call.setup._ExtractInterfaceMetadata(result),
+ mock.call.setup._ExtractInterfaceMetadata(result['networkInterfaces']),
+ mock.call.setup.distro_utils.RestartNetworking(self.mock_setup.logger),
]
self.assertEqual(mocks.mock_calls, expected_calls)
diff --git a/packages/python-google-compute-engine/google_compute_engine/tests/compat_test.py b/packages/python-google-compute-engine/google_compute_engine/tests/compat_test.py
index 803efef..2e8a128 100644
--- a/packages/python-google-compute-engine/google_compute_engine/tests/compat_test.py
+++ b/packages/python-google-compute-engine/google_compute_engine/tests/compat_test.py
@@ -73,14 +73,10 @@ class CompatTest(unittest.TestCase):
test_cases = {
('Fedora', '28', ''):
google_compute_engine.distro_lib.el_7.utils,
- ('debian', '8.10', ''):
- google_compute_engine.distro_lib.debian_8.utils,
('debian', '9.3', ''):
google_compute_engine.distro_lib.debian_9.utils,
('debian', '10.3', ''):
google_compute_engine.distro_lib.debian_9.utils,
- ('SUSE Linux Enterprise Server', '11', 'x86_64'):
- google_compute_engine.distro_lib.sles_11.utils,
('SUSE Linux Enterprise Server', '12', 'x86_64'):
google_compute_engine.distro_lib.sles_12.utils,
('SUSE Linux Enterprise Server', '13', 'x86_64'):
diff --git a/packages/python-google-compute-engine/packaging/debian/changelog b/packages/python-google-compute-engine/packaging/debian/changelog
index d169640..85cd567 100644
--- a/packages/python-google-compute-engine/packaging/debian/changelog
+++ b/packages/python-google-compute-engine/packaging/debian/changelog
@@ -1,5 +1,13 @@
python-google-compute-engine (1:20190801.00-g1) stable; urgency=medium
+ * Fix setup.py version to be compliant with legacy builds.
+ * Detect hostname changes.
+ * Use non-numeric project ID in generated boto.cfg for GSUtil.
+
+ -- Google Cloud Team <gc-team@google.com> Thu, 05 Sep 2019 11:08:18 -0700
+
+python-google-compute-engine (1:20190801.00-g1) stable; urgency=medium
+
* Re-enable boto config and drop writing plugin directory.
* Fix metadata script retrieval.
diff --git a/packages/python-google-compute-engine/packaging/setup_deb.sh b/packages/python-google-compute-engine/packaging/setup_deb.sh
index 9dc8306..ed321c8 100755
--- a/packages/python-google-compute-engine/packaging/setup_deb.sh
+++ b/packages/python-google-compute-engine/packaging/setup_deb.sh
@@ -14,7 +14,7 @@
# limitations under the License.
NAME="python-google-compute-engine"
-VERSION="20190801.00"
+VERSION="20190905.00"
working_dir=${PWD}
if [[ $(basename "$working_dir") != $NAME ]]; then
diff --git a/packages/python-google-compute-engine/packaging/setup_rpm.sh b/packages/python-google-compute-engine/packaging/setup_rpm.sh
index f926673..8d5e05d 100755
--- a/packages/python-google-compute-engine/packaging/setup_rpm.sh
+++ b/packages/python-google-compute-engine/packaging/setup_rpm.sh
@@ -14,7 +14,7 @@
# limitations under the License.
NAME="python-google-compute-engine"
-VERSION="20190801.00"
+VERSION="20190905.00"
rpm_working_dir=/tmp/rpmpackage/${NAME}-${VERSION}
working_dir=${PWD}
diff --git a/packages/python-google-compute-engine/setup.py b/packages/python-google-compute-engine/setup.py
index c51b5ff..e955081 100755
--- a/packages/python-google-compute-engine/setup.py
+++ b/packages/python-google-compute-engine/setup.py
@@ -37,7 +37,7 @@ setuptools.setup(
name='google-compute-engine',
packages=setuptools.find_packages(),
url='https://github.com/GoogleCloudPlatform/compute-image-packages',
- version='20190801.00',
+ version='20190801.0',
# Entry points create scripts in /usr/bin that call a function.
entry_points={
'console_scripts': [