aws.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package integrations
  2. import (
  3. "gorm.io/gorm"
  4. "github.com/aws/aws-sdk-go/aws"
  5. "github.com/aws/aws-sdk-go/aws/credentials"
  6. "github.com/aws/aws-sdk-go/aws/session"
  7. token "sigs.k8s.io/aws-iam-authenticator/pkg/token"
  8. )
  9. // AWSIntegration is an auth mechanism that uses a AWS IAM user to
  10. // authenticate
  11. type AWSIntegration struct {
  12. gorm.Model
  13. // The id of the user that linked this auth mechanism
  14. UserID uint `json:"user_id"`
  15. // The project that this integration belongs to
  16. ProjectID uint `json:"project_id"`
  17. // The AWS entity this is linked to (individual or organization)
  18. AWSEntityID string `json:"aws-entity-id"`
  19. // The AWS caller identity (ARN) which linked this service
  20. AWSCallerID string `json:"aws-caller-id"`
  21. // The optional AWS region (required by some session configurations)
  22. AWSRegion string `json:"aws_region"`
  23. // ------------------------------------------------------------------
  24. // All fields encrypted before storage.
  25. // ------------------------------------------------------------------
  26. // The AWS cluster ID
  27. // See https://github.com/kubernetes-sigs/aws-iam-authenticator#what-is-a-cluster-id
  28. AWSClusterID []byte `json:"aws_cluster_id"`
  29. // The AWS access key for this IAM user
  30. AWSAccessKeyID []byte `json:"aws_access_key_id"`
  31. // The AWS secret key for this IAM user
  32. AWSSecretAccessKey []byte `json:"aws_secret_access_key"`
  33. // An optional session token, if the user is assuming a role
  34. AWSSessionToken []byte `json:"aws_session_token"`
  35. }
  36. // AWSIntegrationExternal is a AWSIntegration to be shared over REST
  37. type AWSIntegrationExternal struct {
  38. ID uint `json:"id"`
  39. // The id of the user that linked this auth mechanism
  40. UserID uint `json:"user_id"`
  41. // The project that this integration belongs to
  42. ProjectID uint `json:"project_id"`
  43. // The AWS entity this is linked to (individual or organization)
  44. AWSEntityID string `json:"aws-entity-id"`
  45. // The AWS caller identity (ARN) which linked this service
  46. AWSCallerID string `json:"aws-caller-id"`
  47. }
  48. // Externalize generates an external KubeIntegration to be shared over REST
  49. func (a *AWSIntegration) Externalize() *AWSIntegrationExternal {
  50. return &AWSIntegrationExternal{
  51. ID: a.ID,
  52. UserID: a.UserID,
  53. ProjectID: a.ProjectID,
  54. AWSEntityID: a.AWSEntityID,
  55. AWSCallerID: a.AWSCallerID,
  56. }
  57. }
  58. // ToProjectIntegration converts an aws integration to a project integration
  59. func (a *AWSIntegration) ToProjectIntegration(
  60. category string,
  61. service IntegrationService,
  62. ) *ProjectIntegration {
  63. return &ProjectIntegration{
  64. ID: a.ID,
  65. ProjectID: a.ProjectID,
  66. AuthMechanism: "aws",
  67. Category: category,
  68. Service: service,
  69. }
  70. }
  71. // GetSession retrieves an AWS session to use based on the access key and secret
  72. // access key
  73. func (a *AWSIntegration) GetSession() (*session.Session, error) {
  74. awsConf := &aws.Config{
  75. Credentials: credentials.NewStaticCredentials(
  76. string(a.AWSAccessKeyID),
  77. string(a.AWSSecretAccessKey),
  78. string(a.AWSSessionToken),
  79. ),
  80. }
  81. if a.AWSRegion != "" {
  82. awsConf.Region = &a.AWSRegion
  83. }
  84. return session.NewSessionWithOptions(session.Options{
  85. SharedConfigState: session.SharedConfigEnable,
  86. Config: *awsConf,
  87. })
  88. }
  89. // GetBearerToken retrieves a bearer token for an AWS account
  90. func (a *AWSIntegration) GetBearerToken(
  91. getTokenCache GetTokenCacheFunc,
  92. setTokenCache SetTokenCacheFunc,
  93. ) (string, error) {
  94. cache, err := getTokenCache()
  95. // check the token cache for a non-expired token
  96. if cache != nil {
  97. if tok := cache.Token; err == nil && !cache.IsExpired() && len(tok) > 0 {
  98. return string(tok), nil
  99. }
  100. }
  101. generator, err := token.NewGenerator(false, false)
  102. if err != nil {
  103. return "", err
  104. }
  105. sess, err := a.GetSession()
  106. if err != nil {
  107. return "", err
  108. }
  109. tok, err := generator.GetWithOptions(&token.GetTokenOptions{
  110. Session: sess,
  111. ClusterID: string(a.AWSClusterID),
  112. })
  113. if err != nil {
  114. return "", err
  115. }
  116. setTokenCache(tok.Token, tok.Expiration)
  117. return tok.Token, nil
  118. }