| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- package forms
- import (
- "encoding/base64"
- "strings"
- "github.com/porter-dev/porter/internal/kubernetes"
- "github.com/porter-dev/porter/internal/models"
- "github.com/porter-dev/porter/internal/repository"
- )
- // ActionResolver exposes an interface for resolving an action as a ServiceAccount.
- // So that actions can be chained together, a pointer to a serviceAccount can be
- // used -- if this points to nil, a new service account is created
- type ActionResolver interface {
- PopulateServiceAccount(repo repository.ServiceAccountRepository) error
- }
- // ServiceAccountActionResolver is the base type for resolving a ServiceAccountAction
- // that belongs to a given ServiceAccountCandidate
- type ServiceAccountActionResolver struct {
- ServiceAccountCandidateID uint `json:"sa_candidate_id" form:"required"`
- SA *models.ServiceAccount
- SACandidate *models.ServiceAccountCandidate
- }
- // PopulateServiceAccount will create a service account if it does not exist,
- // or will append a new cluster given by a ServiceAccountCandidate to the
- // ServiceAccount
- func (sar *ServiceAccountActionResolver) PopulateServiceAccount(
- repo repository.ServiceAccountRepository,
- ) error {
- var err error
- id := sar.ServiceAccountCandidateID
- if sar.SACandidate == nil {
- sar.SACandidate, err = repo.ReadServiceAccountCandidate(id)
- if err != nil {
- return err
- }
- }
- rawConf, err := kubernetes.GetRawConfigFromBytes(sar.SACandidate.Kubeconfig)
- if err != nil {
- return err
- }
- context := rawConf.Contexts[rawConf.CurrentContext]
- authInfoName := context.AuthInfo
- authInfo := rawConf.AuthInfos[authInfoName]
- clusterName := context.Cluster
- cluster := rawConf.Clusters[clusterName]
- modelCluster := models.Cluster{
- Name: clusterName,
- LocationOfOrigin: cluster.LocationOfOrigin,
- Server: cluster.Server,
- TLSServerName: cluster.TLSServerName,
- InsecureSkipTLSVerify: cluster.InsecureSkipTLSVerify,
- }
- if len(cluster.CertificateAuthorityData) > 0 {
- modelCluster.CertificateAuthorityData = cluster.CertificateAuthorityData
- }
- if sar.SA == nil {
- sar.SA = &models.ServiceAccount{
- ProjectID: sar.SACandidate.ProjectID,
- Kind: sar.SACandidate.Kind,
- Clusters: []models.Cluster{modelCluster},
- AuthMechanism: sar.SACandidate.AuthMechanism,
- LocationOfOrigin: authInfo.LocationOfOrigin,
- Impersonate: authInfo.Impersonate,
- ImpersonateGroups: strings.Join(authInfo.ImpersonateGroups, ","),
- }
- } else {
- doesClusterExist := false
- for _, cluster := range sar.SA.Clusters {
- if cluster.Name == sar.SACandidate.ClusterName && cluster.Server == sar.SACandidate.ClusterEndpoint {
- doesClusterExist = true
- }
- }
- if !doesClusterExist {
- sar.SA.Clusters = append(sar.SA.Clusters, modelCluster)
- }
- }
- if len(authInfo.ClientCertificateData) > 0 {
- sar.SA.ClientCertificateData = authInfo.ClientCertificateData
- }
- if len(authInfo.ClientKeyData) > 0 {
- sar.SA.ClientKeyData = authInfo.ClientKeyData
- }
- if authInfo.Token != "" {
- sar.SA.Token = authInfo.Token
- }
- if authInfo.Username != "" {
- sar.SA.Username = authInfo.Username
- }
- if authInfo.Password != "" {
- sar.SA.Password = authInfo.Password
- }
- if authInfo.AuthProvider != nil && authInfo.AuthProvider.Name == "oidc" {
- if url, ok := authInfo.AuthProvider.Config["idp-issuer-url"]; ok {
- sar.SA.OIDCIssuerURL = url
- }
- if clientID, ok := authInfo.AuthProvider.Config["client-id"]; ok {
- sar.SA.OIDCClientID = clientID
- }
- if clientSecret, ok := authInfo.AuthProvider.Config["client-secret"]; ok {
- sar.SA.OIDCClientSecret = clientSecret
- }
- if caData, ok := authInfo.AuthProvider.Config["idp-certificate-authority-data"]; ok {
- // based on the implementation, the oidc plugin expects the data to be base64 encoded,
- // which means we will not decode it here
- // reference: https://github.com/kubernetes/kubernetes/blob/9dfb4c876bfca7a5ae84259fae2bc337ed90c2d7/staging/src/k8s.io/client-go/plugin/pkg/client/auth/oidc/oidc.go#L135
- sar.SA.OIDCCertificateAuthorityData = caData
- }
- if idToken, ok := authInfo.AuthProvider.Config["id-token"]; ok {
- sar.SA.OIDCIDToken = idToken
- }
- if refreshToken, ok := authInfo.AuthProvider.Config["refresh-token"]; ok {
- sar.SA.OIDCRefreshToken = refreshToken
- }
- }
- return nil
- }
- // ClusterCADataAction contains the base64 encoded cluster CA data
- type ClusterCADataAction struct {
- *ServiceAccountActionResolver
- ClusterCAData string `json:"cluster_ca_data" form:"required"`
- }
- // PopulateServiceAccount will add cluster ca data to a cluster in the ServiceAccount's
- // list of clusters
- func (cda *ClusterCADataAction) PopulateServiceAccount(
- repo repository.ServiceAccountRepository,
- ) error {
- err := cda.ServiceAccountActionResolver.PopulateServiceAccount(repo)
- if err != nil {
- return err
- }
- saCandidate := cda.ServiceAccountActionResolver.SACandidate
- for i, cluster := range cda.ServiceAccountActionResolver.SA.Clusters {
- if cluster.Name == saCandidate.ClusterName && cluster.Server == saCandidate.ClusterEndpoint {
- decoded, err := base64.StdEncoding.DecodeString(cda.ClusterCAData)
- // skip if decoding error
- if err != nil {
- return err
- }
- (&cluster).CertificateAuthorityData = decoded
- cda.ServiceAccountActionResolver.SA.Clusters[i] = cluster
- }
- }
- return nil
- }
- // ClientCertDataAction contains the base64 encoded cluster cert data
- type ClientCertDataAction struct {
- *ServiceAccountActionResolver
- ClientCertData string `json:"client_cert_data" form:"required"`
- }
- // PopulateServiceAccount will add client CA data to a ServiceAccount
- func (ccda *ClientCertDataAction) PopulateServiceAccount(
- repo repository.ServiceAccountRepository,
- ) error {
- err := ccda.ServiceAccountActionResolver.PopulateServiceAccount(repo)
- if err != nil {
- return err
- }
- decoded, err := base64.StdEncoding.DecodeString(ccda.ClientCertData)
- // skip if decoding error
- if err != nil {
- return err
- }
- ccda.ServiceAccountActionResolver.SA.ClientCertificateData = decoded
- return nil
- }
- // ClientKeyDataAction contains the base64 encoded cluster key data
- type ClientKeyDataAction struct {
- *ServiceAccountActionResolver
- ClientKeyData string `json:"client_key_data" form:"required"`
- }
- // PopulateServiceAccount will add client CA data to a ServiceAccount
- func (ckda *ClientKeyDataAction) PopulateServiceAccount(
- repo repository.ServiceAccountRepository,
- ) error {
- err := ckda.ServiceAccountActionResolver.PopulateServiceAccount(repo)
- if err != nil {
- return err
- }
- decoded, err := base64.StdEncoding.DecodeString(ckda.ClientKeyData)
- // skip if decoding error
- if err != nil {
- return err
- }
- ckda.ServiceAccountActionResolver.SA.ClientKeyData = decoded
- return nil
- }
- // OIDCIssuerDataAction contains the base64 encoded IDP issuer CA data
- type OIDCIssuerDataAction struct {
- *ServiceAccountActionResolver
- OIDCIssuerCAData string `json:"oidc_idp_issuer_ca_data" form:"required"`
- }
- // PopulateServiceAccount will add OIDC issuer CA data to a ServiceAccount
- func (oida *OIDCIssuerDataAction) PopulateServiceAccount(
- repo repository.ServiceAccountRepository,
- ) error {
- err := oida.ServiceAccountActionResolver.PopulateServiceAccount(repo)
- if err != nil {
- return err
- }
- // based on the implementation, the oidc plugin expects the data to be base64 encoded,
- // which means we will not decode it here
- // reference: https://github.com/kubernetes/kubernetes/blob/9dfb4c876bfca7a5ae84259fae2bc337ed90c2d7/staging/src/k8s.io/client-go/plugin/pkg/client/auth/oidc/oidc.go#L135
- oida.ServiceAccountActionResolver.SA.OIDCCertificateAuthorityData = oida.OIDCIssuerCAData
- return nil
- }
- // TokenDataAction contains the token data to use
- type TokenDataAction struct {
- *ServiceAccountActionResolver
- TokenData string `json:"token_data" form:"required"`
- }
- // PopulateServiceAccount will add bearer token data to a ServiceAccount
- func (tda *TokenDataAction) PopulateServiceAccount(
- repo repository.ServiceAccountRepository,
- ) error {
- err := tda.ServiceAccountActionResolver.PopulateServiceAccount(repo)
- if err != nil {
- return err
- }
- tda.ServiceAccountActionResolver.SA.Token = tda.TokenData
- return nil
- }
- // GCPKeyDataAction contains the GCP key data
- type GCPKeyDataAction struct {
- *ServiceAccountActionResolver
- GCPKeyData string `json:"gcp_key_data" form:"required"`
- }
- // PopulateServiceAccount will add GCP key data to a ServiceAccount
- func (gkda *GCPKeyDataAction) PopulateServiceAccount(
- repo repository.ServiceAccountRepository,
- ) error {
- err := gkda.ServiceAccountActionResolver.PopulateServiceAccount(repo)
- if err != nil {
- return err
- }
- gkda.ServiceAccountActionResolver.SA.GCPKeyData = []byte(gkda.GCPKeyData)
- return nil
- }
- // AWSDataAction contains the AWS data (access id, key)
- type AWSDataAction struct {
- *ServiceAccountActionResolver
- AWSAccessKeyID string `json:"aws_access_key_id" form:"required"`
- AWSSecretAccessKey string `json:"aws_secret_access_key" form:"required"`
- AWSClusterID string `json:"aws_cluster_id" form:"required"`
- }
- // PopulateServiceAccount will add GCP key data to a ServiceAccount
- func (akda *AWSDataAction) PopulateServiceAccount(
- repo repository.ServiceAccountRepository,
- ) error {
- err := akda.ServiceAccountActionResolver.PopulateServiceAccount(repo)
- if err != nil {
- return err
- }
- akda.ServiceAccountActionResolver.SA.AWSAccessKeyID = akda.AWSAccessKeyID
- akda.ServiceAccountActionResolver.SA.AWSSecretAccessKey = akda.AWSSecretAccessKey
- akda.ServiceAccountActionResolver.SA.AWSClusterID = akda.AWSClusterID
- return nil
- }
|