fix: add involves edge from task to agent:nomos at creation
Plus sync vendor directory for Docker build compatibility.
This commit is contained in:
244
vendor/github.com/infisical/go-sdk/packages/util/auth.go
generated
vendored
Normal file
244
vendor/github.com/infisical/go-sdk/packages/util/auth.go
generated
vendored
Normal file
@@ -0,0 +1,244 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
credentials "cloud.google.com/go/iam/credentials/apiv1"
|
||||
"cloud.google.com/go/iam/credentials/apiv1/credentialspb"
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/config"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"google.golang.org/api/option"
|
||||
)
|
||||
|
||||
func GetKubernetesServiceAccountToken(serviceAccountTokenPath string) (string, error) {
|
||||
|
||||
if serviceAccountTokenPath == "" {
|
||||
serviceAccountTokenPath = DEFAULT_KUBERNETES_SERVICE_ACCOUNT_TOKEN_PATH
|
||||
}
|
||||
|
||||
token, err := os.ReadFile(serviceAccountTokenPath)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(token), nil
|
||||
|
||||
}
|
||||
|
||||
func buildAzureMetadataServiceURL(resource string, clientID string) string {
|
||||
azureURL := AZURE_METADATA_SERVICE_URL + AZURE_DEFAULT_RESOURCE
|
||||
if resource != "" {
|
||||
azureURL = AZURE_METADATA_SERVICE_URL + url.QueryEscape(resource)
|
||||
}
|
||||
if clientID != "" {
|
||||
azureURL += "&client_id=" + url.QueryEscape(clientID)
|
||||
}
|
||||
return azureURL
|
||||
}
|
||||
|
||||
// GetAzureMetadataToken fetches a JWT from the Azure IMDS endpoint.
|
||||
// The optional clientID parameter targets a specific User-Assigned Managed Identity;
|
||||
// pass "" for System-Assigned Managed Identity.
|
||||
func GetAzureMetadataToken(httpClient *resty.Client, customResource string, clientID string) (string, error) {
|
||||
|
||||
type AzureMetadataResponse struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
}
|
||||
|
||||
metadataResponse := AzureMetadataResponse{}
|
||||
|
||||
response, err := httpClient.R().
|
||||
SetResult(&metadataResponse).
|
||||
SetHeader("Metadata", "true").
|
||||
SetHeader("Accept", "application/json").
|
||||
Get(buildAzureMetadataServiceURL(customResource, clientID))
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if response.IsError() {
|
||||
return "", fmt.Errorf("GetAzureMetadataToken: Unsuccessful response [%v %v] [status-code=%v] [Error: %s]", response.Request.Method, response.Request.URL, response.StatusCode(), TryParseErrorBody(response))
|
||||
}
|
||||
|
||||
return metadataResponse.AccessToken, nil
|
||||
}
|
||||
|
||||
func GetGCPMetadataToken(httpClient *resty.Client, identityID string) (string, error) {
|
||||
|
||||
res, err := httpClient.R().
|
||||
SetHeader("Metadata-Flavor", "Google").
|
||||
Get(fmt.Sprintf("http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=%s&format=full", identityID))
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if res.IsError() {
|
||||
return "", fmt.Errorf("GetGCPMetadataToken: Unsuccessful response [%v %v] [status-code=%v] [Error: %s]", res.Request.Method, res.Request.URL, res.StatusCode(), TryParseErrorBody(res))
|
||||
}
|
||||
|
||||
return res.String(), nil
|
||||
|
||||
}
|
||||
|
||||
func GetAwsEC2IdentityDocumentRegion(timeout int) (string, error) {
|
||||
|
||||
type AwsIdentityDocument struct {
|
||||
Region string `json:"region"`
|
||||
}
|
||||
|
||||
httpClient := resty.New().SetTimeout(time.Duration(timeout) * time.Millisecond)
|
||||
|
||||
res, err := httpClient.R().
|
||||
SetHeader("X-aws-ec2-metadata-token-ttl-seconds", "21600").
|
||||
Put(AWS_EC2_METADATA_TOKEN_URL)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if res.IsError() {
|
||||
return "", fmt.Errorf("GetAwsEC2IdentityDocumentRegion: Unsuccessful response [%v %v] [status-code=%v] [Error: %s]", res.Request.Method, res.Request.URL, res.StatusCode(), TryParseErrorBody(res))
|
||||
}
|
||||
|
||||
metadataToken := res.String()
|
||||
|
||||
res, err = httpClient.R().
|
||||
SetHeader("X-aws-ec2-metadata-token", metadataToken).
|
||||
SetHeader("Accept", "application/json").
|
||||
Get(AWS_EC2_INSTANCE_IDENTITY_DOCUMENT_URL)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if res.IsError() {
|
||||
return "", fmt.Errorf("GetAwsEC2IdentityDocumentRegion: Unsuccessful response [%v %v] [status-code=%v] [Error: %s]", res.Request.Method, res.Request.URL, res.StatusCode(), TryParseErrorBody(res))
|
||||
}
|
||||
|
||||
// For some reason using .SetResult(&AwsIdentityDocument{}) doesn't work and just results in an empty object. This works though..
|
||||
var identityDocument AwsIdentityDocument
|
||||
err = json.Unmarshal(res.Body(), &identityDocument)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return identityDocument.Region, nil
|
||||
|
||||
}
|
||||
|
||||
func GetGCPIamServiceAccountToken(identityID string, serviceAccountKeyPath string) (string, error) {
|
||||
|
||||
type JwtPayload struct {
|
||||
Sub string `json:"sub"`
|
||||
Aud string `json:"aud"`
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
serviceAccountKey, err := os.ReadFile(serviceAccountKeyPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var creds map[string]string
|
||||
if err := json.Unmarshal(serviceAccountKey, &creds); err != nil {
|
||||
return "", fmt.Errorf("failed to unmarshal service account key: %v", err)
|
||||
}
|
||||
|
||||
clientEmail := creds["client_email"]
|
||||
if clientEmail == "" {
|
||||
return "", fmt.Errorf("client email not found in service account key")
|
||||
}
|
||||
|
||||
payload := JwtPayload{
|
||||
Sub: clientEmail,
|
||||
Aud: identityID,
|
||||
}
|
||||
|
||||
payloadJSON, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to marshal JWT payload: %v", err)
|
||||
}
|
||||
|
||||
iamCredentialsClient, err := credentials.NewIamCredentialsClient(ctx, option.WithCredentialsFile(serviceAccountKeyPath)) //nolint:staticcheck // deprecated but no drop-in replacement available yet
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create IAM credentials client: %v", err)
|
||||
}
|
||||
|
||||
defer iamCredentialsClient.Close() //nolint:errcheck
|
||||
|
||||
signJwtRequest := &credentialspb.SignJwtRequest{
|
||||
Name: fmt.Sprintf("projects/-/serviceAccounts/%s", clientEmail),
|
||||
Payload: string(payloadJSON),
|
||||
}
|
||||
|
||||
resp, err := iamCredentialsClient.SignJwt(ctx, signJwtRequest)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to sign JWT: %v. Ensure the IAM Service Account Credentials API is enabled", err)
|
||||
}
|
||||
|
||||
signedJwt := resp.SignedJwt
|
||||
if signedJwt == "" {
|
||||
return "", fmt.Errorf("failed to sign JWT: signedJwt is empty")
|
||||
}
|
||||
|
||||
return signedJwt, nil
|
||||
|
||||
}
|
||||
|
||||
func GetAwsRegion() (string, error) {
|
||||
// in Lambda environments, the region is available in the AWS_REGION environment variable
|
||||
region := os.Getenv("AWS_REGION")
|
||||
|
||||
if region != "" {
|
||||
return region, nil
|
||||
}
|
||||
|
||||
// in EC2 environments, the region is available in the identity doc
|
||||
|
||||
region, err := GetAwsEC2IdentityDocumentRegion(5000)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return region, nil
|
||||
|
||||
}
|
||||
|
||||
func RetrieveAwsCredentials() (credentials aws.Credentials, region string, err error) {
|
||||
presetAwsCfg, err := config.LoadDefaultConfig(context.TODO())
|
||||
|
||||
if err == nil && presetAwsCfg.Region != "" {
|
||||
creds, err := presetAwsCfg.Credentials.Retrieve(context.TODO())
|
||||
if err == nil {
|
||||
return creds, presetAwsCfg.Region, nil
|
||||
}
|
||||
}
|
||||
|
||||
awsRegion, err := GetAwsRegion()
|
||||
if err != nil {
|
||||
return aws.Credentials{}, "", err
|
||||
}
|
||||
|
||||
awsCfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(awsRegion))
|
||||
if err != nil {
|
||||
return aws.Credentials{}, "", fmt.Errorf("unable to load SDK config, %v", err)
|
||||
}
|
||||
|
||||
creds, err := awsCfg.Credentials.Retrieve(context.TODO())
|
||||
if err != nil {
|
||||
return aws.Credentials{}, "", fmt.Errorf("error retrieving credentials: %v", err)
|
||||
}
|
||||
|
||||
return creds, awsRegion, nil
|
||||
}
|
||||
92
vendor/github.com/infisical/go-sdk/packages/util/constants.go
generated
vendored
Normal file
92
vendor/github.com/infisical/go-sdk/packages/util/constants.go
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// Auth related:
|
||||
const (
|
||||
INFISICAL_AUTH_ORGANIZATION_SLUG_ENV_NAME = "INFISICAL_AUTH_ORGANIZATION_SLUG"
|
||||
|
||||
// Universal auth:
|
||||
INFISICAL_UNIVERSAL_AUTH_CLIENT_ID_ENV_NAME = "INFISICAL_UNIVERSAL_AUTH_CLIENT_ID"
|
||||
INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET_ENV_NAME = "INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET"
|
||||
|
||||
// GCP auth:
|
||||
INFISICAL_GCP_AUTH_IDENTITY_ID_ENV_NAME = "INFISICAL_GCP_AUTH_IDENTITY_ID"
|
||||
INFISICAL_GCP_IAM_SERVICE_ACCOUNT_KEY_FILE_PATH_ENV_NAME = "INFISICAL_GCP_IAM_SERVICE_ACCOUNT_KEY_FILE_PATH"
|
||||
|
||||
// AWS auth:
|
||||
INFISICAL_AWS_IAM_AUTH_IDENTITY_ID_ENV_NAME = "INFISICAL_AWS_IAM_AUTH_IDENTITY_ID"
|
||||
|
||||
// Azure auth:
|
||||
INFISICAL_AZURE_AUTH_IDENTITY_ID_ENV_NAME = "INFISICAL_AZURE_AUTH_IDENTITY_ID"
|
||||
INFISICAL_AZURE_AUTH_CLIENT_ID_ENV_NAME = "INFISICAL_AZURE_AUTH_CLIENT_ID"
|
||||
|
||||
// OCI auth:
|
||||
INFISICAL_OCI_AUTH_IDENTITY_ID_ENV_NAME = "INFISICAL_OCI_AUTH_IDENTITY_ID"
|
||||
|
||||
// LDAP auth:
|
||||
INFISICAL_LDAP_AUTH_IDENTITY_ID_ENV_NAME = "INFISICAL_LDAP_AUTH_IDENTITY_ID"
|
||||
|
||||
// Kubernetes auth:
|
||||
INFISICAL_KUBERNETES_IDENTITY_ID_ENV_NAME = "INFISICAL_KUBERNETES_IDENTITY_ID"
|
||||
INFISICAL_KUBERNETES_SERVICE_ACCOUNT_TOKEN_PATH_ENV_NAME = "INFISICAL_KUBERNETES_SERVICE_ACCOUNT_TOKEN_PATH"
|
||||
|
||||
// OIDC auth:
|
||||
INFISICAL_OIDC_AUTH_IDENTITY_ID_ENV_NAME = "INFISICAL_OIDC_AUTH_IDENTITY_ID"
|
||||
|
||||
// Access token:
|
||||
INFISICAL_ACCESS_TOKEN_ENV_NAME = "INFISICAL_ACCESS_TOKEN"
|
||||
|
||||
// AWS metadata service:
|
||||
AWS_EC2_METADATA_TOKEN_URL = "http://169.254.169.254/latest/api/token"
|
||||
AWS_EC2_INSTANCE_IDENTITY_DOCUMENT_URL = "http://169.254.169.254/latest/dynamic/instance-identity/document"
|
||||
|
||||
// Azure metadata service:
|
||||
AZURE_METADATA_SERVICE_URL = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=" // End of the URL needs to be appended with the resource
|
||||
AZURE_DEFAULT_RESOURCE = "https%3A%2F%2Fmanagement.azure.com/"
|
||||
)
|
||||
|
||||
type AuthMethod string
|
||||
|
||||
const (
|
||||
ACCESS_TOKEN AuthMethod = "ACCESS_TOKEN"
|
||||
UNIVERSAL_AUTH AuthMethod = "UNIVERSAL_AUTH"
|
||||
GCP_ID_TOKEN AuthMethod = "GCP_ID_TOKEN"
|
||||
GCP_IAM AuthMethod = "GCP_IAM"
|
||||
AWS_IAM AuthMethod = "AWS_IAM"
|
||||
KUBERNETES AuthMethod = "KUBERNETES"
|
||||
AZURE AuthMethod = "AZURE"
|
||||
OIDC_AUTH AuthMethod = "OIDC_AUTH"
|
||||
JWT_AUTH AuthMethod = "JWT_AUTH"
|
||||
LDAP_AUTH AuthMethod = "LDAP_AUTH"
|
||||
OCI_AUTH AuthMethod = "OCI_AUTH"
|
||||
)
|
||||
|
||||
// SSH related:
|
||||
type CertKeyAlgorithm string
|
||||
|
||||
const (
|
||||
RSA2048 CertKeyAlgorithm = "RSA_2048"
|
||||
RSA4096 CertKeyAlgorithm = "RSA_4096"
|
||||
ECDSAP256 CertKeyAlgorithm = "EC_prime256v1"
|
||||
ECDSAP384 CertKeyAlgorithm = "EC_secp384r1"
|
||||
)
|
||||
|
||||
type SshCertType string
|
||||
|
||||
const (
|
||||
UserCert SshCertType = "user"
|
||||
HostCert SshCertType = "host"
|
||||
)
|
||||
|
||||
// General:
|
||||
const (
|
||||
DEFAULT_INFISICAL_API_URL = "https://app.infisical.com/api"
|
||||
DEFAULT_KUBERNETES_SERVICE_ACCOUNT_TOKEN_PATH = "/var/run/secrets/kubernetes.io/serviceaccount/token"
|
||||
)
|
||||
|
||||
var ErrContextCanceled = errors.New("context canceled")
|
||||
var ErrContextDeadlineExceeded error = context.DeadlineExceeded
|
||||
146
vendor/github.com/infisical/go-sdk/packages/util/helper.go
generated
vendored
Normal file
146
vendor/github.com/infisical/go-sdk/packages/util/helper.go
generated
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/infisical/go-sdk/packages/models"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
func AppendAPIEndpoint(siteUrl string) string {
|
||||
// Ensure the address does not already end with "/api"
|
||||
if strings.HasSuffix(siteUrl, "/api") {
|
||||
return siteUrl
|
||||
}
|
||||
|
||||
// Check if the address ends with a slash and append accordingly
|
||||
if siteUrl[len(siteUrl)-1] == '/' {
|
||||
return siteUrl + "api"
|
||||
}
|
||||
return siteUrl + "/api"
|
||||
}
|
||||
|
||||
func PrintWarning(logger zerolog.Logger, message string) {
|
||||
logger.Warn().Msgf("[Infisical] Warning: %v", message)
|
||||
}
|
||||
|
||||
func EnsureUniqueSecretsByKey(secrets *[]models.Secret, skipUniqueKey bool) {
|
||||
secretMap := make(map[string]models.Secret)
|
||||
|
||||
// Move secrets to a map to ensure uniqueness
|
||||
for _, secret := range *secrets {
|
||||
var key string
|
||||
if skipUniqueKey {
|
||||
// Create a composite key using both SecretPath and SecretKey
|
||||
key = secret.SecretPath + ":" + secret.SecretKey
|
||||
} else {
|
||||
// Use only SecretKey for global uniqueness
|
||||
key = secret.SecretKey
|
||||
}
|
||||
secretMap[key] = secret
|
||||
}
|
||||
|
||||
// Clear the slice
|
||||
*secrets = (*secrets)[:0]
|
||||
|
||||
// Refill the slice from the map
|
||||
for _, secret := range secretMap {
|
||||
*secrets = append(*secrets, secret)
|
||||
}
|
||||
}
|
||||
|
||||
// containsSecret checks if the given key exists in the slice of secrets
|
||||
func ContainsSecret(secrets []models.Secret, key string) bool {
|
||||
for _, secret := range secrets {
|
||||
if secret.SecretKey == key {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Helper function to sort the secrets by key so we can create a consistent output
|
||||
func SortSecretsByKeys(secrets []models.Secret) []models.Secret {
|
||||
sort.Slice(secrets, func(i, j int) bool {
|
||||
return secrets[i].SecretKey < secrets[j].SecretKey
|
||||
})
|
||||
return secrets
|
||||
}
|
||||
|
||||
/*
|
||||
If the status code is 400, there will most likely always be a body.
|
||||
The body is a json object with a message key. we need to try to parse it, but if it fails, we can just return an empty string.
|
||||
But if the status code is 500, there may not be a body. if there is, it will be a json object with a message key. we need to try to parse it, but if it fails, we can just return an empty string
|
||||
*/
|
||||
func TryParseErrorBody(res *resty.Response) string {
|
||||
if res == nil || !res.IsError() {
|
||||
return ""
|
||||
}
|
||||
|
||||
body := res.String()
|
||||
if body == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
type ErrorResponse struct {
|
||||
Message string `json:"message"`
|
||||
ReqId string `json:"reqId"`
|
||||
}
|
||||
|
||||
// stringify zod body entirely
|
||||
if res.StatusCode() == 422 {
|
||||
return body
|
||||
}
|
||||
|
||||
// now we have a string, we need to try to parse it as json
|
||||
var errorResponse ErrorResponse
|
||||
err := json.Unmarshal([]byte(body), &errorResponse)
|
||||
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return errorResponse.Message
|
||||
}
|
||||
|
||||
func TryExtractReqId(res *resty.Response) string {
|
||||
if res == nil || !res.IsError() {
|
||||
return ""
|
||||
}
|
||||
|
||||
type ErrorResponse struct {
|
||||
ReqId string `json:"reqId"`
|
||||
}
|
||||
|
||||
var errorResponse ErrorResponse
|
||||
|
||||
err := json.Unmarshal([]byte(res.String()), &errorResponse)
|
||||
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return errorResponse.ReqId
|
||||
}
|
||||
|
||||
func SleepWithContext(ctx context.Context, duration time.Duration) error {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-time.After(duration):
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func ComputeCacheKeyFromBytes(bytes []byte, feature string) string {
|
||||
key := sha256.Sum256(bytes)
|
||||
return fmt.Sprintf("%s-%s", feature, hex.EncodeToString(key[:]))
|
||||
}
|
||||
Reference in New Issue
Block a user