Skip to content

Commit

Permalink
Merge pull request #821 from spiffxp/gcloud-secret-over-git-crypt
Browse files Browse the repository at this point in the history
Use gcloud secrets instead of git-crypt for groups
  • Loading branch information
k8s-ci-robot authored Apr 30, 2020
2 parents ec5e3cd + 2c744ab commit 7ecef2f
Show file tree
Hide file tree
Showing 9 changed files with 249 additions and 16 deletions.
26 changes: 26 additions & 0 deletions audit/audit-gcp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,32 @@ gcloud \
#### gcloud alpha monitoring channels list > "projects/${PROJECT}/services/monitoring.channels.json"
#### gcloud alpha monitoring channel-descriptors list > "projects/${PROJECT}/services/monitoring.channel-descriptors.json"
;;
secretmanager)
gcloud \
secrets list \
--project=k8s-gsuite \
--format="value(name)" \
| while read -r SECRET; do
path="projects/${PROJECT}/secrets/${SECRET}"
mkdir -p "${path}"
gcloud \
secrets describe "${SECRET}" \
--project="${PROJECT}" \
--format=json \
> "${path}/description.json"
gcloud \
secrets versions list "${SECRET}" \
--project="${PROJECT}" \
--format=json \
> "${path}/versions.json"
gcloud \
secrets get-iam-policy "${SECRET}" \
--project="${PROJECT}" \
--format=json \
| jq 'del(.etag)' \
> "${path}/iam.json"
done
;;
storage-api)
gsutil ls -p "${PROJECT}" \
| awk -F/ '{print $3}' \
Expand Down
2 changes: 0 additions & 2 deletions groups/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,4 @@ default: run

.PHONY: run
run:
git-crypt unlock
GO111MODULE=on go run reconcile.go $(runargs)
git-crypt lock
4 changes: 2 additions & 2 deletions groups/config.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Configuration for the kubernetes.io Google Groups setup

# file path of the google groups service account token
token-file: k8s-gsuite-1781c2662b57.json
# Secret version of the service account key to use
secret-version: projects/k8s-gsuite/secrets/gsuite-groups-manager_key/versions/latest

# Email id of the bot service account
bot-id: wg-k8s-infra-api@kubernetes.io
Expand Down
8 changes: 5 additions & 3 deletions groups/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ module k8s.io/k8s.io/groups
go 1.12

require (
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
google.golang.org/api v0.9.0
cloud.google.com/go v0.56.0
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
google.golang.org/api v0.20.0
google.golang.org/genproto v0.0.0-20200429120912-1f37eeb960b2
gopkg.in/yaml.v2 v2.2.2
k8s.io/test-infra v0.0.0-20191024183346-202cefeb6ff5
)
152 changes: 152 additions & 0 deletions groups/go.sum

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions groups/groups.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,18 @@ groups:
- spiffxp@google.com
- thockin@google.com

- email-id: k8s-infra-group-admins@kubernetes.io
name: Group Administrators for kubernetes.io
description: |-
People trusted to admin kubernetes.io google groups by
running the groups reconciler
settings:
ReconcileMembers: "true"
members:
- cblecker@gmail.com
- davanum@gmail.com
- spiffxp@google.com
- thockin@google.com
#
# Push groups: k8s-infra-push-*
#
Expand Down
Binary file removed groups/k8s-gsuite-1781c2662b57.json
Binary file not shown.
37 changes: 28 additions & 9 deletions groups/reconcile.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ import (
"reflect"
"time"

secretmanager "cloud.google.com/go/secretmanager/apiv1"
"golang.org/x/net/context"
"golang.org/x/oauth2/google"
"google.golang.org/api/admin/directory/v1"
"google.golang.org/api/googleapi"
"google.golang.org/api/groupssettings/v1"
secretmanagerpb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1"
"gopkg.in/yaml.v2"

"k8s.io/test-infra/pkg/genyaml"
Expand All @@ -43,8 +45,8 @@ type Config struct {
// the email id for the bot/service account
BotID string `yaml:"bot-id"`

// the file with the authentication information
TokenFile string `yaml:"token-file,omitempty"`
// the gcloud secret containing a service account key to authenticate with
SecretVersion string `yaml:"secret-version,omitempty"`

// the file with the groups/members information
GroupsFile string `yaml:"groups-file,omitempty"`
Expand Down Expand Up @@ -107,18 +109,14 @@ func main() {
log.Fatal(err)
}

jsonCredentials, err := ioutil.ReadFile(config.TokenFile)
if err != nil {
log.Fatal(err)
}
serviceAccountKey, err := accessSecretVersion(config.SecretVersion)

credential, err := google.JWTConfigFromJSON(jsonCredentials, admin.AdminDirectoryUserReadonlyScope,
credential, err := google.JWTConfigFromJSON(serviceAccountKey, admin.AdminDirectoryUserReadonlyScope,
admin.AdminDirectoryGroupScope,
admin.AdminDirectoryGroupMemberScope,
groupssettings.AppsGroupsSettingsScope)
if err != nil {
log.Fatalf("Unable to parse client secret file to config: %v\n. "+
"Please run 'git-crypt unlock'", err)
log.Fatalf("Unable to authenticate using key in secret-version %s, %v", config.SecretVersion, err)
}
credential.Subject = config.BotID

Expand Down Expand Up @@ -621,3 +619,24 @@ func deepCopySettings(a, b interface{}) {
byt, _ := json.Marshal(a)
json.Unmarshal(byt, b)
}

// accessSecretVersion accesses the payload for the given secret version if one exists
// secretVersion is of the form projects/{project}/secrets/{secret}/versions/{version}
func accessSecretVersion(secretVersion string) ([]byte, error) {
ctx := context.Background()
client, err := secretmanager.NewClient(ctx)
if err != nil {
return nil, fmt.Errorf("failed to create secretmanager client: %v", err)
}

req := &secretmanagerpb.AccessSecretVersionRequest{
Name: secretVersion,
}

result, err := client.AccessSecretVersion(ctx, req)
if err != nil {
return nil, fmt.Errorf("failed to access secret version: %v", err)
}

return result.Payload.Data, nil
}
24 changes: 24 additions & 0 deletions infra/gcp/ensure-gsuite.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ GSUITE_SVCACCT="gsuite-groups-manager"
# delegation.
GSUITE_USER="wg-k8s-infra-api@kubernetes.io"

# The group of people authorized to access the secret that contains
# the service account key
GSUITE_GROUP_ADMINS="k8s-infra-group-admins@kubernetes.io"


color 6 "Ensuring project exists: ${PROJECT}"
ensure_project "${PROJECT}"
Expand All @@ -55,13 +59,33 @@ enable_api "${PROJECT}" admin.googleapis.com
color 6 "Enabling the GSuite groups API"
enable_api "${PROJECT}" groupssettings.googleapis.com

color 6 "Enabling the Secret Manager API"
enable_api "${PROJECT}" secretmanager.googleapis.com

# Create a service account for gsuite to grant access to.
color 6 "Creating service account for ${GSUITE_SVCACCT}"
ensure_service_account \
"${PROJECT}" \
"${GSUITE_SVCACCT}" \
"Grants access to the googlegroups API in kubernetes.io GSuite"

# Ensure the service account has a key in a secret accessible by the right people
if ! gcloud --project="${PROJECT}" \
secrets describe "${GSUITE_SVCACCT}_key" >/dev/null 2>&1; then
color 6 "A human with admin privileges needs to run the following:"
color 4 " gcloud iam service-accounts keys create tmp.json --project=${PROJECT} \\"
color 4 " --iam-account=$(svc_acct_email "${PROJECT}" "${GSUITE_SVCACCT}") && \\"
color 4 " gcloud secrets create --project=${PROJECT} --replication-policy=automatic \\"
color 4 " --data-file=tmp.json ${GSUITE_SVCACCT}_key && \\"
color 4 " rm tmp.json"
else
color 6 "Empowering ${GSUITE_GROUP_ADMINS} to access the ${GSUITE_SVCACCT}_key secret"
gcloud --project="${PROJECT}" \
secrets add-iam-policy-binding "${GSUITE_SVCACCT}_key" \
--member="group:${GSUITE_GROUP_ADMINS}" \
--role="roles/secretmanager.secretAccessor"
fi

# Grant project owner for now because I have no idea exactly which specific
# permissions are needed, and the UI is really not helping.
color 6 "Empowering ${GSUITE_USER}"
Expand Down

0 comments on commit 7ecef2f

Please sign in to comment.