5.10. 토큰 인증
5.10.1. 클라우드 공급자의 Operator에 대한 토큰 인증
많은 클라우드 공급자는 단기적이고 제한된 권한 보안 인증 정보를 제공하는 계정 토큰을 사용하여 인증을 활성화할 수 있습니다.
OpenShift Container Platform에는 클라우드 공급자 인증 정보를 CRD(사용자 정의 리소스 정의)로 관리하는 CCO(Cloud Credential Operator)가 포함되어 있습니다. CCO는 CredentialsRequest
CR(사용자 정의 리소스)에서 동기화되므로 OpenShift Container Platform 구성 요소가 필요한 특정 권한으로 클라우드 공급자 인증 정보를 요청할 수 있습니다.
이전 버전에서는 CCO가 수동 모드인 클러스터에서 OLM(Operator Lifecycle Manager)에서 관리하는 Operator에 종종 사용자가 필요한 클라우드 인증 정보를 수동으로 프로비저닝하는 방법에 대한 자세한 지침이 제공되었습니다.
OpenShift Container Platform 4.14부터 CCO는 특정 클라우드 공급자에서 단기 인증 정보를 사용하도록 활성화된 클러스터에서 실행되는 시기를 감지할 수 있습니다. 그러면 Operator 작성자가 Operator에서 업데이트된 CCO를 지원할 수 있는 경우 특정 인증 정보를 반자동으로 프로비저닝할 수 있습니다.
5.10.2. AWS STS를 사용하여 OLM 관리 Operator의 CCO 기반 워크플로
AWS에서 실행되는 OpenShift Container Platform 클러스터가 STS(Security Token Service) 모드인 경우 클러스터가 AWS 및 OpenShift Container Platform의 기능을 사용하여 애플리케이션 수준에서 IAM 역할을 사용하고 있음을 의미합니다. STS를 사용하면 애플리케이션에서 IAM 역할을 가정할 수 있는 JSON 웹 토큰(JWT)을 제공할 수 있습니다.
JWT에는 서비스 계정에 대한 임시 부여 권한을 허용하는 sts:AssumeRoleWithWebIdentity
IAM 작업에 대한 Amazon Resource Name(ARN)이 포함됩니다. JWT에는 AWS IAM에서 검증할 수 있는 ProjectedServiceAccountToken
의 서명 키가 포함되어 있습니다. 서명된 서비스 계정 토큰 자체는 AWS 역할을 가정하는 데 필요한 JWT로 사용됩니다.
CCO(Cloud Credential Operator)는 기본적으로 클라우드 공급자에서 실행되는 OpenShift Container Platform 클러스터에 설치된 클러스터 Operator입니다. STS의 목적을 위해 CCO는 다음 기능을 제공합니다.
- STS 지원 클러스터에서 실행 중인 시기 감지
-
AWS 리소스에 대한 Operator 액세스 권한을 부여하는 데 필요한 정보를 제공하는 필드가 있는지
CredentialsRequest
오브젝트를 확인합니다.
CCO는 수동 모드에서도 이 탐지를 수행합니다. 올바르게 구성되면 CCO는 Operator 네임스페이스에 필요한 액세스 정보가 있는 Secret
오브젝트를 생성합니다.
OpenShift Container Platform 4.14부터 CCO는 STS 워크플로우에 필요한 정보가 포함된 시크릿
생성을 요청할 수 있는 CredentialsRequest
오브젝트의 확장된 사용을 통해 이 작업을 반자동화할 수 있습니다. 사용자는 웹 콘솔 또는 CLI에서 Operator를 설치할 때 역할 ARN을 제공할 수 있습니다.
업데이트에 대한 자동 승인이 있는 서브스크립션은 업데이트하기 전에 권한을 변경할 수 있으므로 권장되지 않습니다. 업데이트에 대한 수동 승인이 있는 서브스크립션을 통해 관리자는 최신 버전의 권한을 확인하고 필요한 단계를 수행한 다음 업데이트할 수 있습니다.
OpenShift Container Platform 4.14 이상에서 업데이트된 CCO와 함께 Operator를 사용할 수 있도록 Operator 작성자로서 STS 토큰 인증을 처리하는 것 외에도 사용자와 이전 CCO 버전의 차이점을 처리하도록 코드를 추가해야 합니다(Operator가 STS 활성화되지 않은 경우). 권장되는 방법은 올바르게 채워진 STS 필드를 사용하여 CredentialsRequest
오브젝트를 제공하고 CCO가 시크릿
을 생성하도록 하는 것입니다.
버전 4.14 이전의 OpenShift Container Platform 클러스터를 지원하려는 경우 CCO 유틸리티(ccoctl
)를 사용하여 STS-enabling 정보를 사용하여 시크릿을 수동으로 생성하는 방법에 대한 지침을 사용자에게 제공하는 것이 좋습니다. 이전 CCO 버전은 클러스터에서 STS 모드를 인식하지 못하며 시크릿을 생성할 수 없습니다.
코드는 나타나지 않는 시크릿을 확인하고 사용자가 제공한 대체 지침을 따르도록 경고해야 합니다. 자세한 내용은 "Alternative Method" 하위 섹션을 참조하십시오.
5.10.2.1. Operator가 AWS STS를 사용하여 CCO 기반 워크플로우를 지원하도록 활성화
OLM(Operator Lifecycle Manager)에서 프로젝트를 실행하도록 프로젝트를 설계하는 Operator 작성자는 CCO(Cloud Credential Operator)를 지원하도록 프로젝트를 사용자 정의하여 Operator를 STS 사용 OpenShift Container Platform 클러스터에서 AWS에 대해 인증할 수 있습니다.
이 방법을 사용하면 Operator에서 CredentialsRequest
오브젝트를 생성하고 결과 Secret
오브젝트를 읽는 데 필요한 RBAC 권한이 필요합니다.
기본적으로 Operator 배포와 관련된 Pod는 serviceAccountToken
볼륨을 마운트하여 결과 Secret
오브젝트에서 서비스 계정 토큰을 참조할 수 있습니다.
전제 조건
- OpenShift Container Platform 4.14 이상
- STS 모드의 클러스터
- OLM 기반 Operator 프로젝트
프로세스
Operator 프로젝트의 CSV(
ClusterServiceVersion
) 오브젝트를 업데이트합니다.Operator에
CredentialsRequests
오브젝트를 생성할 수 있는 RBAC 권한이 있는지 확인합니다.예 5.16.
clusterPermissions
목록의 예# ... install: spec: clusterPermissions: - rules: - apiGroups: - "cloudcredential.openshift.io" resources: - credentialsrequests verbs: - create - delete - get - list - patch - update - watch
AWS STS를 사용하여 이 CCO 기반 워크플로우 방법에 대한 지원을 클레임하려면 다음 주석을 추가합니다.
# ... metadata: annotations: features.operators.openshift.io/token-auth-aws: "true"
Operator 프로젝트 코드를 업데이트합니다.
Subscription
오브젝트를 통해 Pod에 설정된 환경 변수에서 ARN 역할을 가져옵니다. 예를 들면 다음과 같습니다.// Get ENV var roleARN := os.Getenv("ROLEARN") setupLog.Info("getting role ARN", "role ARN = ", roleARN) webIdentityTokenPath := "/var/run/secrets/openshift/serviceaccount/token"
CredentialsRequest
개체를 패치하고 적용할 준비가 되었는지 확인합니다. 예를 들면 다음과 같습니다.예 5.17.
CredentialsRequest
오브젝트 생성 예import ( minterv1 "github.com/openshift/cloud-credential-operator/pkg/apis/cloudcredential/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) var in = minterv1.AWSProviderSpec{ StatementEntries: []minterv1.StatementEntry{ { Action: []string{ "s3:*", }, Effect: "Allow", Resource: "arn:aws:s3:*:*:*", }, }, STSIAMRoleARN: "<role_arn>", } var codec = minterv1.Codec var ProviderSpec, _ = codec.EncodeProviderSpec(in.DeepCopyObject()) const ( name = "<credential_request_name>" namespace = "<namespace_name>" ) var CredentialsRequestTemplate = &minterv1.CredentialsRequest{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: "openshift-cloud-credential-operator", }, Spec: minterv1.CredentialsRequestSpec{ ProviderSpec: ProviderSpec, SecretRef: corev1.ObjectReference{ Name: "<secret_name>", Namespace: namespace, }, ServiceAccountNames: []string{ "<service_account_name>", }, CloudTokenPath: "", }, }
또는 YAML 형식의
CredentialsRequest
오브젝트(예: Operator 프로젝트 코드의 일부)에서 시작하는 경우 다르게 처리할 수 있습니다.예 5.18. YAML 형식의
CredentialsRequest
오브젝트 생성 예// CredentialsRequest is a struct that represents a request for credentials type CredentialsRequest struct { APIVersion string `yaml:"apiVersion"` Kind string `yaml:"kind"` Metadata struct { Name string `yaml:"name"` Namespace string `yaml:"namespace"` } `yaml:"metadata"` Spec struct { SecretRef struct { Name string `yaml:"name"` Namespace string `yaml:"namespace"` } `yaml:"secretRef"` ProviderSpec struct { APIVersion string `yaml:"apiVersion"` Kind string `yaml:"kind"` StatementEntries []struct { Effect string `yaml:"effect"` Action []string `yaml:"action"` Resource string `yaml:"resource"` } `yaml:"statementEntries"` STSIAMRoleARN string `yaml:"stsIAMRoleARN"` } `yaml:"providerSpec"` // added new field CloudTokenPath string `yaml:"cloudTokenPath"` } `yaml:"spec"` } // ConsumeCredsRequestAddingTokenInfo is a function that takes a YAML filename and two strings as arguments // It unmarshals the YAML file to a CredentialsRequest object and adds the token information. func ConsumeCredsRequestAddingTokenInfo(fileName, tokenString, tokenPath string) (*CredentialsRequest, error) { // open a file containing YAML form of a CredentialsRequest file, err := os.Open(fileName) if err != nil { return nil, err } defer file.Close() // create a new CredentialsRequest object cr := &CredentialsRequest{} // decode the yaml file to the object decoder := yaml.NewDecoder(file) err = decoder.Decode(cr) if err != nil { return nil, err } // assign the string to the existing field in the object cr.Spec.CloudTokenPath = tokenPath // return the modified object return cr, nil }
참고Operator 번들에
CredentialsRequest
오브젝트를 추가하는 것은 현재 지원되지 않습니다.인증 정보 요청에 ARN 및 웹 ID 토큰 경로를 추가하고 Operator 초기화 중에 적용합니다.
예 5.19. Operator 초기화 중
CredentialsRequest
오브젝트 적용 예// apply CredentialsRequest on install credReq := credreq.CredentialsRequestTemplate credReq.Spec.CloudTokenPath = webIdentityTokenPath c := mgr.GetClient() if err := c.Create(context.TODO(), credReq); err != nil { if !errors.IsAlreadyExists(err) { setupLog.Error(err, "unable to create CredRequest") os.Exit(1) } }
Operator에서 조정 중인 다른 항목과 함께 호출되는 다음 예와 같이 Operator가 CCO에서
Secret
오브젝트가 표시될 때까지 기다릴 수 있습니다.예 5.20.
Secret
오브젝트 대기의 예// WaitForSecret is a function that takes a Kubernetes client, a namespace, and a v1 "k8s.io/api/core/v1" name as arguments // It waits until the secret object with the given name exists in the given namespace // It returns the secret object or an error if the timeout is exceeded func WaitForSecret(client kubernetes.Interface, namespace, name string) (*v1.Secret, error) { // set a timeout of 10 minutes timeout := time.After(10 * time.Minute) 1 // set a polling interval of 10 seconds ticker := time.NewTicker(10 * time.Second) // loop until the timeout or the secret is found for { select { case <-timeout: // timeout is exceeded, return an error return nil, fmt.Errorf("timed out waiting for secret %s in namespace %s", name, namespace) // add to this error with a pointer to instructions for following a manual path to a Secret that will work on STS case <-ticker.C: // polling interval is reached, try to get the secret secret, err := client.CoreV1().Secrets(namespace).Get(context.Background(), name, metav1.GetOptions{}) if err != nil { if errors.IsNotFound(err) { // secret does not exist yet, continue waiting continue } else { // some other error occurred, return it return nil, err } } else { // secret is found, return it return secret, nil } } } }
- 1
시간 초과
값은 CCO에서 추가된CredentialsRequest
오브젝트를 감지하고Secret
오브젝트를 생성하는 속도의 추정치를 기반으로 합니다. Operator가 아직 클라우드 리소스에 액세스하지 않는 이유를 확인할 수 있는 클러스터 관리자에게 시간을 낮추거나 사용자 정의 피드백을 생성하는 것을 고려할 수 있습니다.
인증 정보 요청에서 CCO에서 생성한 보안을 읽고 해당 시크릿의 데이터가 포함된 AWS 구성 파일을 생성하여 AWS 구성을 설정합니다.
예 5.21. AWS 구성 생성 예
func SharedCredentialsFileFromSecret(secret *corev1.Secret) (string, error) { var data []byte switch { case len(secret.Data["credentials"]) > 0: data = secret.Data["credentials"] default: return "", errors.New("invalid secret for aws credentials") } f, err := ioutil.TempFile("", "aws-shared-credentials") if err != nil { return "", errors.Wrap(err, "failed to create file for shared credentials") } defer f.Close() if _, err := f.Write(data); err != nil { return "", errors.Wrapf(err, "failed to write credentials to %s", f.Name()) } return f.Name(), nil }
중요시크릿은 존재하는 것으로 가정되지만 Operator 코드는 이 시크릿을 사용할 때 대기하고 재시도하여 CCO에 시간을 할애하여 보안을 생성해야 합니다.
또한 대기 기간은 결국 OpenShift Container Platform 클러스터 버전 및 CCO가 STS 탐지를 사용하여
CredentialsRequest
오브젝트 워크플로를 지원하지 않는 이전 버전일 수 있음을 사용자에게 시간 초과하고 경고해야 합니다. 이러한 경우 다른 방법을 사용하여 시크릿을 추가해야 함을 사용자에게 지시합니다.AWS SDK 세션을 구성합니다. 예를 들면 다음과 같습니다.
예 5.22. AWS SDK 세션 구성 예
sharedCredentialsFile, err := SharedCredentialsFileFromSecret(secret) if err != nil { // handle error } options := session.Options{ SharedConfigState: session.SharedConfigEnable, SharedConfigFiles: []string{sharedCredentialsFile}, }
5.10.2.2. 역할 사양
Operator 설명에는 설치 전에 생성하는 데 필요한 역할의 세부 정보가 포함되어야 합니다. 이는 관리자가 실행할 수 있는 스크립트 형태로 이상적입니다. 예를 들면 다음과 같습니다.
예 5.23. 역할 생성 스크립트의 예
#!/bin/bash set -x AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text) OIDC_PROVIDER=$(oc get authentication cluster -ojson | jq -r .spec.serviceAccountIssuer | sed -e "s/^https:\/\///") NAMESPACE=my-namespace SERVICE_ACCOUNT_NAME="my-service-account" POLICY_ARN_STRINGS="arn:aws:iam::aws:policy/AmazonS3FullAccess" read -r -d '' TRUST_RELATIONSHIP <<EOF { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::${AWS_ACCOUNT_ID}:oidc-provider/${OIDC_PROVIDER}" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "${OIDC_PROVIDER}:sub": "system:serviceaccount:${NAMESPACE}:${SERVICE_ACCOUNT_NAME}" } } } ] } EOF echo "${TRUST_RELATIONSHIP}" > trust.json aws iam create-role --role-name "$SERVICE_ACCOUNT_NAME" --assume-role-policy-document file://trust.json --description "role for demo" while IFS= read -r POLICY_ARN; do echo -n "Attaching $POLICY_ARN ... " aws iam attach-role-policy \ --role-name "$SERVICE_ACCOUNT_NAME" \ --policy-arn "${POLICY_ARN}" echo "ok." done <<< "$POLICY_ARN_STRINGS"
5.10.2.3. 문제 해결
5.10.2.3.1. 인증 실패
인증이 실패하면 Operator에 제공된 토큰을 사용하여 웹 ID가 있는 역할을 가정할 수 있는지 확인합니다.
프로세스
Pod에서 토큰을 추출합니다.
$ oc exec operator-pod -n <namespace_name> \ -- cat /var/run/secrets/openshift/serviceaccount/token
Pod에서 ARN 역할을 추출합니다.
$ oc exec operator-pod -n <namespace_name> \ -- cat /<path>/<to>/<secret_name> 1
- 1
- 경로에 root를 사용하지 마십시오.
웹 ID 토큰을 사용하여 역할을 가정합니다.
$ aws sts assume-role-with-web-identity \ --role-arn $ROLEARN \ --role-session-name <session_name> \ --web-identity-token $TOKEN
5.10.2.3.2. secret이 올바르게 마운트되지 않음
루트가 아닌 사용자로 실행되는 Pod는 기본적으로 AWS 공유 인증 정보 파일이 존재하는 /root
디렉토리에 쓸 수 없습니다. 보안이 AWS 인증 정보 파일 경로에 올바르게 마운트되지 않은 경우 시크릿을 다른 위치에 마운트하고 AWS SDK에서 공유 인증 정보 파일 옵션을 활성화하는 것이 좋습니다.
5.10.2.4. 대체 방법
Operator 작성자의 대체 방법으로는 Operator를 설치하기 전에 사용자가 CCO(Cloud Credential Operator)에 대한 CredentialsRequest
오브젝트를 생성해야 함을 나타낼 수 있습니다.
Operator 명령은 다음을 사용자에게 표시해야 합니다.
-
지침에 YAML 인라인을 제공하거나 사용자를 다운로드 위치를 가리켜
CredentialsRequest
오브젝트의 YAML 버전을 제공합니다. -
사용자에게
CredentialsRequest
오브젝트를 생성하도록 지시합니다.
OpenShift Container Platform 4.14 이상에서는 적절한 STS 정보가 추가된 클러스터에 CredentialsRequest
오브젝트가 표시된 후 Operator에서 CCO 생성 시크릿
을 읽거나 마운트하여 CSV(클러스터 서비스 버전)에서 마운트를 정의할 수 있습니다.
이전 버전의 OpenShift Container Platform의 경우 Operator 지침도 사용자에게 다음을 표시해야 합니다.
-
CCO 유틸리티(
ccoctl
)를 사용하여CredentialsRequest
오브젝트에서Secret
YAML 오브젝트를 생성합니다. -
적절한 네임스페이스의 클러스터에
Secret
오브젝트를 적용
Operator는 여전히 결과 시크릿을 사용하여 클라우드 API와 통신할 수 있어야 합니다. 이 경우 Operator가 설치되기 전에 사용자가 시크릿을 생성하므로 Operator는 다음 중 하나를 수행할 수 있습니다.
-
CSV 내의
Deployment
오브젝트에 명시적 마운트 정의 -
권장 "AWS STS를 사용하여 CCO 기반 워크플로우를 지원하도록 Operator 활성화" 메서드와 같이 API 서버에서
Secret
오브젝트를 프로그래밍 방식으로 읽습니다.
5.10.3. Microsoft Entra Workload ID가 있는 OLM 관리 Operator의 CCO 기반 워크플로
Azure에서 실행되는 OpenShift Container Platform 클러스터가 Workload Identity / Federated Identity 모드에 있는 경우 클러스터가 Azure 및 OpenShift Container Platform의 기능을 활용하여 애플리케이션 수준에서 사용자가 할당한 관리 ID 또는 앱 등록을 적용합니다.
CCO(Cloud Credential Operator)는 기본적으로 클라우드 공급자에서 실행되는 OpenShift Container Platform 클러스터에 설치된 클러스터 Operator입니다. OpenShift Container Platform 4.14.8부터 CCO는 워크로드 ID가 있는 OLM 관리 Operator의 워크플로우를 지원합니다.
Workload ID의 목적을 위해 CCO는 다음 기능을 제공합니다.
- 워크로드 ID 지원 클러스터에서 실행 중인 시기 감지
-
Azure 리소스에 대한 Operator 액세스 권한을 부여하는 데 필요한 정보를 제공하는 필드가 있는지
CredentialsRequest
오브젝트를 확인합니다.
CCO는 워크로드 ID 워크플로에 필요한 정보가 포함된 시크릿
생성을 요청할 수 있는 CredentialsRequest
오브젝트의 확장된 사용을 통해 이 프로세스를 반자동화할 수 있습니다.
업데이트에 대한 자동 승인이 있는 서브스크립션은 업데이트하기 전에 권한을 변경할 수 있으므로 권장되지 않습니다. 업데이트에 대한 수동 승인이 있는 서브스크립션을 통해 관리자는 최신 버전의 권한을 확인하고 필요한 단계를 수행한 다음 업데이트할 수 있습니다.
OpenShift Container Platform 4.14 이상에서 업데이트된 CCO와 함께 Operator를 사용할 수 있도록 Operator 작성자로서 Workload ID 토큰 인증(Operator가 아직 활성화되지 않은 경우)을 처리하는 것 외에도 사용자와 이전 CCO 버전의 차이점을 처리하도록 코드를 추가해야 합니다. 권장되는 방법은 올바르게 채워진 Workload ID 필드를 사용하여 CredentialsRequest
오브젝트를 제공하고 CCO가 Secret
오브젝트를 생성하도록 하는 것입니다.
버전 4.14 이전의 OpenShift Container Platform 클러스터를 지원하려는 경우 CCO 유틸리티(ccoctl
)를 사용하여 워크로드 ID를 사용하여 시크릿을 수동으로 생성하는 방법에 대한 지침을 사용자에게 제공하는 것이 좋습니다. 이전 CCO 버전은 클러스터에서 Workload ID 모드를 인식하지 못하며 시크릿을 생성할 수 없습니다.
코드는 나타나지 않는 시크릿을 확인하고 사용자가 제공한 대체 지침을 따르도록 경고해야 합니다.
Workload ID를 사용한 인증에는 다음 정보가 필요합니다.
-
azure_client_id
-
azure_tenant_id
-
azure_region
-
azure_subscription_id
-
azure_federated_token_file
클러스터 관리자는 웹 콘솔의 Operator 설치 페이지를 통해 설치 시 이 정보를 제공할 수 있습니다. 그런 다음 이 정보는 Subscription
오브젝트에 Operator Pod의 환경 변수로 전파됩니다.
추가 리소스
5.10.3.1. Microsoft Entra Workload ID를 사용하여 CCO 기반 워크플로우를 지원할 수 있도록 Operator 활성화
OLM(Operator Lifecycle Manager)에서 프로젝트를 실행하도록 프로젝트를 설계하는 Operator 작성자는 CCO(Cloud Credential Operator)를 지원하도록 프로젝트를 사용자 정의하여 Operator에서 Microsoft Entra Workload ID 지원 OpenShift Container Platform 클러스터에 대해 인증할 수 있습니다.
이 방법을 사용하면 Operator에서 CredentialsRequest
오브젝트를 생성하고 결과 Secret
오브젝트를 읽는 데 필요한 RBAC 권한이 필요합니다.
기본적으로 Operator 배포와 관련된 Pod는 serviceAccountToken
볼륨을 마운트하여 결과 Secret
오브젝트에서 서비스 계정 토큰을 참조할 수 있습니다.
전제 조건
- OpenShift Container Platform 4.14 이상
- 워크로드 ID 모드의 클러스터
- OLM 기반 Operator 프로젝트
프로세스
Operator 프로젝트의 CSV(
ClusterServiceVersion
) 오브젝트를 업데이트합니다.Operator에
CredentialsRequests
오브젝트를 생성할 수 있는 RBAC 권한이 있는지 확인합니다.예 5.24.
clusterPermissions
목록의 예# ... install: spec: clusterPermissions: - rules: - apiGroups: - "cloudcredential.openshift.io" resources: - credentialsrequests verbs: - create - delete - get - list - patch - update - watch
Workload ID를 사용하여 CCO 기반 워크플로우 방법에 대한 지원을 요청하려면 다음 주석을 추가합니다.
# ... metadata: annotations: features.operators.openshift.io/token-auth-azure: "true"
Operator 프로젝트 코드를 업데이트합니다.
Subscription
오브젝트를 통해 포드에 설정된 환경 변수에서 클라이언트 ID, 테넌트 ID, 서브스크립션 ID를 가져옵니다. 예를 들면 다음과 같습니다.// Get ENV var clientID := os.Getenv("CLIENTID") tenantID := os.Getenv("TENANTID") subscriptionID := os.Getenv("SUBSCRIPTIONID") azureFederatedTokenFile := "/var/run/secrets/openshift/serviceaccount/token"
CredentialsRequest
개체를 패치하고 적용할 준비가 되었는지 확인합니다.참고Operator 번들에
CredentialsRequest
오브젝트를 추가하는 것은 현재 지원되지 않습니다.인증 정보 및 웹 ID 토큰 경로를 인증 정보 요청에 추가하고 Operator 초기화 중에 적용합니다.
예 5.25. Operator 초기화 중
CredentialsRequest
오브젝트 적용 예// apply CredentialsRequest on install credReqTemplate.Spec.AzureProviderSpec.AzureClientID = clientID credReqTemplate.Spec.AzureProviderSpec.AzureTenantID = tenantID credReqTemplate.Spec.AzureProviderSpec.AzureRegion = "centralus" credReqTemplate.Spec.AzureProviderSpec.AzureSubscriptionID = subscriptionID credReqTemplate.CloudTokenPath = azureFederatedTokenFile c := mgr.GetClient() if err := c.Create(context.TODO(), credReq); err != nil { if !errors.IsAlreadyExists(err) { setupLog.Error(err, "unable to create CredRequest") os.Exit(1) } }
Operator에서 조정 중인 다른 항목과 함께 호출되는 다음 예와 같이 Operator가 CCO에서
Secret
오브젝트가 표시될 때까지 기다릴 수 있습니다.예 5.26.
Secret
오브젝트 대기의 예// WaitForSecret is a function that takes a Kubernetes client, a namespace, and a v1 "k8s.io/api/core/v1" name as arguments // It waits until the secret object with the given name exists in the given namespace // It returns the secret object or an error if the timeout is exceeded func WaitForSecret(client kubernetes.Interface, namespace, name string) (*v1.Secret, error) { // set a timeout of 10 minutes timeout := time.After(10 * time.Minute) 1 // set a polling interval of 10 seconds ticker := time.NewTicker(10 * time.Second) // loop until the timeout or the secret is found for { select { case <-timeout: // timeout is exceeded, return an error return nil, fmt.Errorf("timed out waiting for secret %s in namespace %s", name, namespace) // add to this error with a pointer to instructions for following a manual path to a Secret that will work on STS case <-ticker.C: // polling interval is reached, try to get the secret secret, err := client.CoreV1().Secrets(namespace).Get(context.Background(), name, metav1.GetOptions{}) if err != nil { if errors.IsNotFound(err) { // secret does not exist yet, continue waiting continue } else { // some other error occurred, return it return nil, err } } else { // secret is found, return it return secret, nil } } } }
- 1
시간 초과
값은 CCO에서 추가된CredentialsRequest
오브젝트를 감지하고Secret
오브젝트를 생성하는 속도의 추정치를 기반으로 합니다. Operator가 아직 클라우드 리소스에 액세스하지 않는 이유를 확인할 수 있는 클러스터 관리자에게 시간을 낮추거나 사용자 정의 피드백을 생성하는 것을 고려할 수 있습니다.
-
Azure로 인증하고 필요한 인증 정보를 수신하기 위해
CredentialsRequest
오브젝트에서 CCO에서 생성한 시크릿을 읽습니다.
5.10.4. GCP 워크로드 ID를 사용하는 OLM 관리 Operator의 CCO 기반 워크플로
GCP(Google Cloud Platform)에서 실행되는 OpenShift Container Platform 클러스터가 GCP(Google Workload Identity/Federated Identity ) 모드에 있는 경우 클러스터가 GCP(Google Cloud Platform) 및 OpenShift Container Platform의 기능을 활용하여 애플리케이션 수준에서 GCP 워크로드 ID에 권한을 적용합니다.
CCO(Cloud Credential Operator)는 기본적으로 클라우드 공급자에서 실행되는 OpenShift Container Platform 클러스터에 설치된 클러스터 Operator입니다. OpenShift Container Platform 4.17부터 CCO는 GCP 워크로드 ID가 있는 OLM 관리 Operator의 워크플로우를 지원합니다.
GCP Workload Identity의 목적을 위해 CCO는 다음과 같은 기능을 제공합니다.
- GCP 워크로드 ID 지원 클러스터에서 실행 중인 시기 감지
-
CredentialsRequest
오브젝트에서 GCP 리소스에 대한 Operator 액세스 권한을 부여하는 데 필요한 정보를 제공하는 필드가 있는지 확인합니다.
CCO는 CredentialsRequest
오브젝트의 확장된 사용을 통해 이 프로세스를 반자동화할 수 있으며, 이는 GCP Workload Identity 워크플로에 필요한 정보가 포함된 시크릿
생성을 요청할 수 있습니다.
업데이트에 대한 자동 승인이 있는 서브스크립션은 업데이트하기 전에 권한을 변경할 수 있으므로 권장되지 않습니다. 업데이트에 대한 수동 승인이 있는 서브스크립션을 통해 관리자는 최신 버전의 권한을 확인하고 필요한 단계를 수행한 다음 업데이트할 수 있습니다.
OpenShift Container Platform 4.17 이상에서 업데이트된 CCO와 함께 Operator를 사용할 수 있도록 Operator 작성자로서 GCP Workload Identity 토큰 인증(Operator가 아직 활성화되지 않은 경우)을 처리하는 것 외에도 사용자와 이전 CCO 버전의 차이점을 처리하도록 코드를 추가해야 합니다. 권장 방법은 올바르게 채워진 GCP Workload Identity 필드를 사용하여 CredentialsRequest
오브젝트를 제공하고 CCO가 Secret
오브젝트를 생성하도록 하는 것입니다.
버전 4.17 이전의 OpenShift Container Platform 클러스터를 지원할 예정인 경우 CCO 유틸리티(ccoctl
)를 사용하여 GCP Workload Identity-enabling 정보를 사용하여 시크릿을 수동으로 생성하는 방법에 대한 지침을 사용자에게 제공하는 것이 좋습니다. 이전 CCO 버전은 클러스터의 GCP Workload Identity 모드를 인식하지 않으며 시크릿을 생성할 수 없습니다.
코드는 나타나지 않는 시크릿을 확인하고 사용자가 제공한 대체 지침을 따르도록 경고해야 합니다.
Google Cloud Platform Workload Identity를 통해 단기 토큰을 사용하여 GCP로 인증하려면 Operator에서 다음 정보를 제공해야 합니다.
AUDIENCE
GCP Workload Identity를 설정할 때 관리자가 GCP에서 생성한
AUDIENCE
값은 다음 형식의 사전 형식의 URL이어야 합니다.//iam.googleapis.com/projects/<project_number>/locations/global/workloadIdentityPools/<pool_id>/providers/<provider_id>
SERVICE_ACCOUNT_EMAIL
SERVICE_ACCOUNT_EMAIL
값은 Operator 작업 중에 가장하는 GCP 서비스 계정 이메일입니다. 예를 들면 다음과 같습니다.<service_account_name>@<project_id>.iam.gserviceaccount.com
클러스터 관리자는 웹 콘솔의 Operator 설치 페이지를 통해 설치 시 이 정보를 제공할 수 있습니다. 그런 다음 이 정보는 Subscription
오브젝트에 Operator Pod의 환경 변수로 전파됩니다.
추가 리소스
5.10.4.1. Operator가 GCP 워크로드 ID를 사용하여 CCO 기반 워크플로우를 지원하도록 활성화
OLM(Operator Lifecycle Manager)에서 프로젝트를 실행하도록 프로젝트를 설계하는 Operator 작성자는 CCO(Cloud Credential Operator)를 지원하도록 프로젝트를 사용자 정의하여 Operator에서 OpenShift Container Platform 클러스터의 Google Cloud Platform 워크로드 ID에 대해 인증할 수 있습니다.
이 방법을 사용하면 Operator에서 CredentialsRequest
오브젝트를 생성하고 결과 Secret
오브젝트를 읽는 데 필요한 RBAC 권한이 필요합니다.
기본적으로 Operator 배포와 관련된 Pod는 serviceAccountToken
볼륨을 마운트하여 결과 Secret
오브젝트에서 서비스 계정 토큰을 참조할 수 있습니다.
전제 조건
- OpenShift Container Platform 4.17 이상
- GCP 워크로드 ID/Federated Identity 모드의 클러스터
- OLM 기반 Operator 프로젝트
프로세스
Operator 프로젝트의 CSV(
ClusterServiceVersion
) 오브젝트를 업데이트합니다.Operator가 웹 ID로 역할을 가정할 수 있도록 CSV에서 Operator 배포에 다음과 같은
volumeMounts
및volumes
필드가 있는지 확인합니다.예 5.27.
volumeMounts
및volumes
필드의 예# ... volumeMounts: - name: bound-sa-token mountPath: /var/run/secrets/openshift/serviceaccount readOnly: true volumes: # This service account token can be used to provide identity outside the cluster. - name: bound-sa-token projected: sources: - serviceAccountToken: path: token audience: openshift
Operator에
CredentialsRequests
오브젝트를 생성할 수 있는 RBAC 권한이 있는지 확인합니다.예 5.28.
clusterPermissions
목록의 예# ... install: spec: clusterPermissions: - rules: - apiGroups: - "cloudcredential.openshift.io" resources: - credentialsrequests verbs: - create - delete - get - list - patch - update - watch
GCP Workload Identity를 사용하여 CCO 기반 워크플로우 방법에 대한 지원을 요청하려면 다음 주석을 추가합니다.
# ... metadata: annotations: features.operators.openshift.io/token-auth-gcp: "true"
Operator 프로젝트 코드를 업데이트합니다.
서브스크립션 구성에 설정된 환경 변수에서
audience
및serviceAccountEmail
값을 가져옵니다.// Get ENV var audience := os.Getenv("AUDIENCE") serviceAccountEmail := os.Getenv("SERVICE_ACCOUNT_EMAIL") gcpIdentityTokenFile := "/var/run/secrets/openshift/serviceaccount/token"
CredentialsRequest
개체를 패치하고 적용할 준비가 되었는지 확인합니다.참고Operator 번들에
CredentialsRequest
오브젝트를 추가하는 것은 현재 지원되지 않습니다.인증 정보 요청에 GCP Workload Identity 변수를 추가하고 Operator 초기화 중에 적용합니다.
예 5.29. Operator 초기화 중
CredentialsRequest
오브젝트 적용 예// apply CredentialsRequest on install credReqTemplate.Spec.GCPProviderSpec.Audience = audience credReqTemplate.Spec.GCPProviderSpec.ServiceAccountEmail = serviceAccountEmail credReqTemplate.CloudTokenPath = gcpIdentityTokenFile c := mgr.GetClient() if err := c.Create(context.TODO(), credReq); err != nil { if !errors.IsAlreadyExists(err) { setupLog.Error(err, "unable to create CredRequest") os.Exit(1) } }
Operator에서 조정 중인 다른 항목과 함께 호출되는 다음 예와 같이 Operator가 CCO에서
Secret
오브젝트가 표시될 때까지 기다릴 수 있습니다.예 5.30.
Secret
오브젝트 대기의 예// WaitForSecret is a function that takes a Kubernetes client, a namespace, and a v1 "k8s.io/api/core/v1" name as arguments // It waits until the secret object with the given name exists in the given namespace // It returns the secret object or an error if the timeout is exceeded func WaitForSecret(client kubernetes.Interface, namespace, name string) (*v1.Secret, error) { // set a timeout of 10 minutes timeout := time.After(10 * time.Minute) 1 // set a polling interval of 10 seconds ticker := time.NewTicker(10 * time.Second) // loop until the timeout or the secret is found for { select { case <-timeout: // timeout is exceeded, return an error return nil, fmt.Errorf("timed out waiting for secret %s in namespace %s", name, namespace) // add to this error with a pointer to instructions for following a manual path to a Secret that will work case <-ticker.C: // polling interval is reached, try to get the secret secret, err := client.CoreV1().Secrets(namespace).Get(context.Background(), name, metav1.GetOptions{}) if err != nil { if errors.IsNotFound(err) { // secret does not exist yet, continue waiting continue } else { // some other error occurred, return it return nil, err } } else { // secret is found, return it return secret, nil } } } }
- 1
시간 초과
값은 CCO에서 추가된CredentialsRequest
오브젝트를 감지하고Secret
오브젝트를 생성하는 속도의 추정치를 기반으로 합니다. Operator가 아직 클라우드 리소스에 액세스하지 않는 이유를 확인할 수 있는 클러스터 관리자에게 시간을 낮추거나 사용자 정의 피드백을 생성하는 것을 고려할 수 있습니다.
시크릿에서
service_account.json
필드를 읽고 이를 사용하여 GCP 클라이언트를 인증합니다.service_account_json := secret.StringData["service_account.json"]