Skip to content

Commit

Permalink
Merge pull request #7 from phasehq/feat--service-accounts-support
Browse files Browse the repository at this point in the history
Feat: service accounts support
  • Loading branch information
nimish-ks authored Nov 5, 2024
2 parents cb2f70e + e14411f commit 7f816f4
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 86 deletions.
14 changes: 6 additions & 8 deletions internal/provider/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ import (
"regexp"
)


const (
// Version of the provider
Version = "0.1.1"
Version = "0.1.2"

// DefaultHostURL is the default host for Phase API
DefaultHostURL = "https://api.phase.dev"
Expand All @@ -27,11 +26,11 @@ type PhaseClient struct {

// Secret represents a secret in the Phase API
type Secret struct {
ID string `json:"id,omitempty"`
Key string `json:"key"`
Value string `json:"value"`
Comment string `json:"comment,omitempty"`
Path string `json:"path,omitempty"`
ID string `json:"id,omitempty"`
Key string `json:"key"`
Value string `json:"value"`
Comment string `json:"comment,omitempty"`
Path string `json:"path,omitempty"`
Override *SecretOverride `json:"override,omitempty"`
}

Expand All @@ -46,5 +45,4 @@ var (
// Compiled regex patterns
PssUserPattern = regexp.MustCompile(`^pss_user:v(\d+):([a-fA-F0-9]{64}):([a-fA-F0-9]{64}):([a-fA-F0-9]{64}):([a-fA-F0-9]{64})$`)
PssServicePattern = regexp.MustCompile(`^pss_service:v(\d+):([a-fA-F0-9]{64}):([a-fA-F0-9]{64}):([a-fA-F0-9]{64}):([a-fA-F0-9]{64})$`)

)
168 changes: 90 additions & 78 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,30 @@ func providerConfigure(ctx context.Context, d *schema.ResourceData) (interface{}
}

func extractTokenInfo(phaseToken string) (string, string) {
if PssUserPattern.MatchString(phaseToken) {
// First, check if it's a service token
if PssServicePattern.MatchString(phaseToken) {
parts := strings.Split(phaseToken, ":")
if len(parts) >= 3 {
return "User", parts[2]
version := parts[1]
bearerToken := parts[2]

// For service tokens with v2
if version == "v2" {
return "ServiceAccount", bearerToken
}
return "Service", bearerToken
}
} else if PssServicePattern.MatchString(phaseToken) {
}

// Then check if it's a user token
if PssUserPattern.MatchString(phaseToken) {
parts := strings.Split(phaseToken, ":")
if len(parts) >= 3 {
return "Service", parts[2]
return "User", parts[2]
}
}
return "", phaseToken // Default to empty token type if no match

return "", phaseToken
}

func resourceSecret() *schema.Resource {
Expand Down Expand Up @@ -253,80 +265,80 @@ func resourceSecretDelete(ctx context.Context, d *schema.ResourceData, meta inte
}

func dataSourceSecrets() *schema.Resource {
return &schema.Resource{
ReadContext: dataSourceSecretsRead,
Schema: map[string]*schema.Schema{
"app_id": {
Type: schema.TypeString,
Required: true,
Description: "The ID of the Phase App.",
},
"env": {
Type: schema.TypeString,
Required: true,
Description: "The environment name.",
},
"path": {
Type: schema.TypeString,
Optional: true,
Default: "/",
Description: "The path to fetch secrets from.",
},
"key": {
Type: schema.TypeString,
Optional: true,
Description: "The key of a specific secret to fetch.",
},
"secrets": {
Type: schema.TypeMap,
Computed: true,
Sensitive: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
}
return &schema.Resource{
ReadContext: dataSourceSecretsRead,
Schema: map[string]*schema.Schema{
"app_id": {
Type: schema.TypeString,
Required: true,
Description: "The ID of the Phase App.",
},
"env": {
Type: schema.TypeString,
Required: true,
Description: "The environment name.",
},
"path": {
Type: schema.TypeString,
Optional: true,
Default: "/",
Description: "The path to fetch secrets from.",
},
"key": {
Type: schema.TypeString,
Optional: true,
Description: "The key of a specific secret to fetch.",
},
"secrets": {
Type: schema.TypeMap,
Computed: true,
Sensitive: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
}
}

func dataSourceSecretsRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*PhaseClient)

appID := d.Get("app_id").(string)
env := d.Get("env").(string)
path := d.Get("path").(string)
key := d.Get("key").(string)

// Determine if we're fetching all secrets
fetchingAll := path == ""

secrets, err := client.ReadSecret(appID, env, key, fmt.Sprintf("Bearer %s", client.TokenType))
if err != nil {
return diag.FromErr(err)
}

secretMap := make(map[string]string)
for _, secret := range secrets {
if fetchingAll || secret.Path == path {
if secret.Override != nil && secret.Override.IsActive {
secretMap[secret.Key] = secret.Override.Value
} else {
secretMap[secret.Key] = secret.Value
}
}
}

if err := d.Set("secrets", secretMap); err != nil {
return diag.FromErr(err)
}

// Set the path in the state
if err := d.Set("path", path); err != nil {
return diag.FromErr(err)
}

// Generate a unique ID for the data source
d.SetId(fmt.Sprintf("%s-%s-%s-%s", appID, env, path, key))

return nil
client := meta.(*PhaseClient)

appID := d.Get("app_id").(string)
env := d.Get("env").(string)
path := d.Get("path").(string)
key := d.Get("key").(string)

// Determine if we're fetching all secrets
fetchingAll := path == ""

secrets, err := client.ReadSecret(appID, env, key, fmt.Sprintf("Bearer %s", client.TokenType))
if err != nil {
return diag.FromErr(err)
}

secretMap := make(map[string]string)
for _, secret := range secrets {
if fetchingAll || secret.Path == path {
if secret.Override != nil && secret.Override.IsActive {
secretMap[secret.Key] = secret.Override.Value
} else {
secretMap[secret.Key] = secret.Value
}
}
}

if err := d.Set("secrets", secretMap); err != nil {
return diag.FromErr(err)
}

// Set the path in the state
if err := d.Set("path", path); err != nil {
return diag.FromErr(err)
}

// Generate a unique ID for the data source
d.SetId(fmt.Sprintf("%s-%s-%s-%s", appID, env, path, key))

return nil
}

0 comments on commit 7f816f4

Please sign in to comment.