provider-gcp icon indicating copy to clipboard operation
provider-gcp copied to clipboard

ProjectID in ProviderConfig not honoured if ServiceAccount credentials are from a different project

Open jgwmaxwell opened this issue 3 years ago • 1 comments

Thanks for all your hard work on this, it's super awesome to see how far it's come and how useful it is.

What happened?

I tried to use a cross-project ServiceAccount to provision resources in another project that it has access to. The creation call for a CloudSQLInstance fails, as it is trying to access the project of the ServiceAccount credentials, not the configured projectID from the ProviderConfig.

How can we reproduce it?

Assuming a configured Crossplane & GCP environment (versions below), the following shell commands should recreate the issue.

MAIN_PROJECT_ID=foobar 
CHILD_PROJECT_ID=bazqux

SA="executor@${MAIN_PROJECT_ID}.iam.gserviceaccount.com"

# create SA in main project
gcloud iam service-accounts create executor --project $MAIN_PROJECT_ID

# ensure child project has sqladmin enabled
gcloud services enable "sqladmin.googleapis.com" --project $CHILD_PROJECT_ID

# add binding to SA in child project
gcloud projects add-iam-policy-binding --role="roles/editor" $CHILD_PROJECT_ID --member "serviceAccount:$SA"

# get service account keyfile
gcloud iam service-accounts keys create creds.json --project $MAIN_PROJECT_ID --iam-account $SA

# create a namespace for the child project
kubectl create ns $CHILD_PROJECT_ID

# create secret for ProviderConfig
kubectl create secret generic -n $CHILD_PROJECT_ID gcp-creds --from-file=key=./creds.json

# create ProviderConfig
cat <<EOF | kubectl apply -f -
apiVersion: gcp.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
  name: ${CHILD_PROJECT_ID}-gcp
spec:
  projectID: ${CHILD_PROJECT_ID}
  credentials:
    source: Secret
    secretRef:
      namespace: ${CHILD_PROJECT_ID}
      name: gcp-creds
      key: key
EOF

# create a database
cat <<EOF | kubectl apply -f -
apiVersion: database.gcp.crossplane.io/v1beta1
kind: CloudSQLInstance
metadata:
  name: cloudsqlpostgresql
  namespace: ${CHILD_PROJECT_ID}
spec:
  forProvider:
    databaseVersion: POSTGRES_9_6
    region: europe-west1
    settings:
      tier: db-custom-1-3840
      dataDiskType: PD_SSD
      dataDiskSizeGb: 10
  providerConfigRef:
    name: ${CHILD_PROJECT_ID}-gcp
  writeConnectionSecretToRef:
    namespace: ${CHILD_PROJECT_ID}
    name: cloudsqlpostgresql-conn
EOF

I was hoping to just open a PR for this, but found it a little difficult to follow my nose to where the issue is. Happy to do the work if someone has a pointer for me?

What environment did it happen in?

Crossplane version: 1.0.0 Crossplane GCP version: 0.15.0 Kubectl: "v1.20.2-dirty - faecb196815e248d3ecfb03c680a4507229c2a56" (compiled for Apple Silicon) Kubernetes version: GKE v1.18.12-gke.1205, COS with Containerd

jgwmaxwell avatar Jan 28 '21 22:01 jgwmaxwell