Google Compute Engine's default behavior creates a potential security vulnerability in CoreOS clusters. When any project member authenticates with GCP, they can SSH into instances as virtually any user - a significant security concern for teams.
GCE handles user creation through metadata-based SSH key management. The instance metadata contains SSH public keys that GCE automatically processes to create corresponding user accounts. The process works like this:
1. Instance boots and reads metadata
2. For each SSH key in metadata:
a. Creates user account if doesn't exist
b. Adds key to ~/.ssh/authorized_keys
3. Updates occur whenever metadata changes
To disable this behavior and enforce your cloud-config specified users exclusively:
# Disable GCE's automatic account creation
sudo systemctl stop google-accounts-daemon
sudo systemctl disable google-accounts-daemon
# Alternatively, block the metadata server
sudo iptables -A OUTPUT -d metadata.google.internal -j DROP
Here's a complete cloud-config example that creates specific users with controlled access:
#cloud-config
users:
- name: admin
groups: sudo,docker
ssh-authorized-keys:
- ssh-rsa AAAAB3Nza... admin@workstation
expire: false
- name: deploy
ssh-authorized-keys:
- ssh-rsa AAAAB3Nza... ci@jenkins
expire: 2024-12-31
Combine with these security best practices:
# Enable SSH key rotation
chage -M 30 admin
# Disable root login
sudo sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
# Restart SSH service
sudo systemctl restart sshd
After implementation:
# Verify accounts
cat /etc/passwd | grep -v nologin
# Check running services
systemctl list-units | grep google
# Test SSH access
ssh -i ~/.ssh/deploy_key deploy@your-instance
Google Compute Engine automatically provisions users through its metadata server when instances boot. This occurs via the following workflow:
1. Instance boots and requests metadata from http://metadata.google.internal
2. The metadata server provides SSH keys from project/instance metadata
3. These keys are injected into ~/.ssh/authorized_keys for corresponding users
4. Users are created on-the-fly when first authenticating
This "just-in-time" user creation means any valid Google identity with appropriate IAM permissions can SSH as any username that doesn't already exist in /etc/passwd.
The automatic user provisioning creates several security concerns:
- No centralized control over user accounts
- No password expiration policies
- Difficulty auditing access (since users are ephemeral)
- Project-level access grants too much privilege
To disable this behavior in CoreOS, we need to modify the cloud-init configuration:
#cloud-config
write_files:
- path: /etc/ssh/sshd_config.d/disable-gce-users.conf
permissions: 0600
owner: root:root
content: |
# Disable GCE metadata-based auth
AuthorizedKeysCommand none
AuthorizedKeysCommandUser nobody
users:
- name: admin
groups: sudo,docker
ssh-authorized-keys:
- ssh-rsa AAAAB3NzaC1yc2E... user@example.com
lock-passwd: false
passwd: $6$rounds=5000$N1yqR2dX$wW0Z6...
For proper user control, implement these additional measures:
# Set up PAM module for password expiration
auth required pam_faillock.so preauth audit silent deny=5 unlock_time=900
auth [success=1 default=bad] pam_unix.so
auth [default=die] pam_faillock.so authfail audit deny=5 unlock_time=900
# Weekly cron job to enforce password changes
0 0 * * 0 /usr/bin/passwd -e admin
Complement the technical controls with proper IAM configuration:
- Use project-level SSH key restrictions
- Implement granular IAM roles (avoid primitive roles)
- Enable OS Login for managed identities
- Set up VPC Service Controls for additional isolation
After implementation, verify the configuration:
# Check SSH config
sudo sshd -T | grep AuthorizedKeysCommand
# Verify user creation attempt fails
gcloud compute ssh unauthorized-user@instance --project=your-project