Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions akeyless/common/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ func ExpandStringList(configured []interface{}) []string {
return vs
}

func ExpandStringMap(raw map[string]interface{}) map[string]string {
out := make(map[string]string, len(raw))
for k, v := range raw {
out[k] = v.(string)
}
return out
}

func ErrorDiagnostics(message string) diag.Diagnostic {
return diag.Diagnostic{
Severity: diag.Error,
Expand Down
11 changes: 11 additions & 0 deletions akeyless/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ func Provider() *schema.Provider {
"akeyless_classic_key": resourceClassicKey(),
"akeyless_dfc_key": resourceDfcKey(),
"akeyless_static_secret": resourceStaticSecret(),
"akeyless_mcp_secret_bearer_token": resourceMcpSecretBearerToken(),
"akeyless_mcp_secret_oauth_authorization_code": resourceMcpSecretOAuthAuthCode(),
"akeyless_mcp_secret_oauth_client_credentials": resourceMcpSecretOAuthClientCreds(),
"akeyless_pki_cert_issuer": resourcePKICertIssuer(),
"akeyless_ssh_cert_issuer": resourceSSHCertIssuer(),
"akeyless_auth_method_api_key": resourceAuthMethodApiKey(),
Expand All @@ -68,6 +71,7 @@ func Provider() *schema.Provider {
"akeyless_auth_method_universal_identity": resourceAuthMethodUniversalIdentity(),
"akeyless_auth_method_kerberos": resourceAuthMethodKerberos(),
"akeyless_certificate": resourceCertificate(),
"akeyless_certificate_discovery": resourceCertificateDiscovery(),
"akeyless_role": resourceRole(),
"akeyless_gateway_allowed_access": resourceGatewayAllowedAccess(),
"akeyless_gateway_cache": resourceGatewayUpdateCache(),
Expand Down Expand Up @@ -103,6 +107,7 @@ func Provider() *schema.Provider {
"akeyless_gateway_migration_aws": resourceGatewayMigrationAws(),
"akeyless_gateway_migration_azure_kv": resourceGatewayMigrationAzureKv(),
"akeyless_gateway_migration_certificate": resourceGatewayMigrationCertificate(),
"akeyless_gateway_migration_conjur": resourceGatewayMigrationConjur(),
"akeyless_gateway_migration_gcp": resourceGatewayMigrationGcp(),
"akeyless_gateway_migration_hashi": resourceGatewayMigrationHashi(),
"akeyless_gateway_migration_k8s": resourceGatewayMigrationK8s(),
Expand Down Expand Up @@ -167,10 +172,13 @@ func Provider() *schema.Provider {
"akeyless_folder_sync": resourceFolderSync(),
"akeyless_folder_sync_all": resourceFolderSyncAll(),
"akeyless_folder": resourceFolder(),
"akeyless_target_anthropic": resourceAnthropicTarget(),
"akeyless_target_artifactory": resourceArtifactoryTarget(),
"akeyless_target_aws": resourceAwsTarget(),
"akeyless_target_azure": resourceAzureTarget(),
"akeyless_target_bedrock": resourceBedrockTarget(),
"akeyless_target_cloudflare": resourceCloudflareTarget(),
"akeyless_target_custom_dns": resourceCustomDnsTarget(),
"akeyless_target_db": resourceDbTarget(),
"akeyless_target_digicert": resourceDigicertTarget(),
"akeyless_target_dockerhub": resourceDockerhubTarget(),
Expand All @@ -184,11 +192,14 @@ func Provider() *schema.Provider {
"akeyless_target_globalsign_atlas": resourceGlobalsignAtlasTarget(),
"akeyless_target_godaddy": resourceGodaddyTarget(),
"akeyless_target_google_trust": resourceGoogleTrustTarget(),
"akeyless_target_grok": resourceGrokTarget(),
"akeyless_target_hashivault": resourceHashiVaultTarget(),
"akeyless_target_k8s": resourceK8sTarget(),
"akeyless_target_keycloak": resourceKeycloakTarget(),
"akeyless_target_ldap": resourceLdapTarget(),
"akeyless_target_lets_encrypt": resourceLetsEncryptTarget(),
"akeyless_target_linked": resourceLinkedTarget(),
"akeyless_target_okta": resourceOktaTarget(),
"akeyless_target_openai": resourceOpenAITarget(),
"akeyless_target_ping": resourcePingTarget(),
"akeyless_target_rabbit": resourceRabbitmqTarget(),
Expand Down
16 changes: 16 additions & 0 deletions akeyless/resource_auth_method_saml.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ func resourceAuthMethodSaml() *schema.Resource {
Description: "A list of additional sub claims delimiters (relevant only for SAML, OIDC, OAuth2/JWT)",
Elem: &schema.Schema{Type: schema.TypeString},
},
"use_dedicated_saml_urls": {
Type: schema.TypeBool,
Optional: true,
Description: "Use dedicated SAML URLs",
},
"access_id": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -159,6 +164,7 @@ func resourceAuthMethodSamlCreate(d *schema.ResourceData, m interface{}) error {
productType := common.ExpandStringList(productTypeSet.List())
subclaimsDelimitersSet := d.Get("subclaims_delimiters").(*schema.Set)
subclaimsDelimiters := common.ExpandStringList(subclaimsDelimitersSet.List())
useDedicatedSamlUrls := d.Get("use_dedicated_saml_urls").(bool)

body := akeyless_api.AuthMethodCreateSAML{
Name: name,
Expand All @@ -180,6 +186,7 @@ func resourceAuthMethodSamlCreate(d *schema.ResourceData, m interface{}) error {
common.GetAkeylessPtr(&body.GwBoundIps, gwBoundIps)
common.GetAkeylessPtr(&body.ProductType, productType)
common.GetAkeylessPtr(&body.SubclaimsDelimiters, subclaimsDelimiters)
common.GetAkeylessPtr(&body.UseDedicatedSamlUrls, useDedicatedSamlUrls)

rOut, resp, err := client.AuthMethodCreateSAML(ctx).Body(body).Execute()
if err != nil {
Expand Down Expand Up @@ -338,6 +345,13 @@ func resourceAuthMethodSamlRead(d *schema.ResourceData, m interface{}) error {
}
}

if rOut.AccessInfo.SamlAccessRules != nil && rOut.AccessInfo.SamlAccessRules.UseDedicatedSamlUrls != nil {
err = d.Set("use_dedicated_saml_urls", *rOut.AccessInfo.SamlAccessRules.UseDedicatedSamlUrls)
if err != nil {
return err
}
}

d.SetId(path)

return nil
Expand Down Expand Up @@ -374,6 +388,7 @@ func resourceAuthMethodSamlUpdate(d *schema.ResourceData, m interface{}) error {
productType := common.ExpandStringList(productTypeSet.List())
subclaimsDelimitersSet := d.Get("subclaims_delimiters").(*schema.Set)
subclaimsDelimiters := common.ExpandStringList(subclaimsDelimitersSet.List())
useDedicatedSamlUrls := d.Get("use_dedicated_saml_urls").(bool)

body := akeyless_api.AuthMethodUpdateSAML{
Name: name,
Expand All @@ -396,6 +411,7 @@ func resourceAuthMethodSamlUpdate(d *schema.ResourceData, m interface{}) error {
common.GetAkeylessPtr(&body.GwBoundIps, gwBoundIps)
common.GetAkeylessPtr(&body.ProductType, productType)
common.GetAkeylessPtr(&body.SubclaimsDelimiters, subclaimsDelimiters)
common.GetAkeylessPtr(&body.UseDedicatedSamlUrls, useDedicatedSamlUrls)

_, resp, err := client.AuthMethodUpdateSAML(ctx).Body(body).Execute()
if err != nil {
Expand Down
26 changes: 26 additions & 0 deletions akeyless/resource_auth_method_universal_identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ func resourceAuthMethodUniversalIdentity() *schema.Resource {
Description: "Token ttl (in minutes)",
Default: 60,
},
"uid_expiration_event_at": {
Type: schema.TypeSet,
Optional: true,
Description: "Trigger an event when Universal Identity Token TTL has reached the specified percentage (e.g. 10, 20, 50)",
Elem: &schema.Schema{Type: schema.TypeString},
},
"audit_logs_claims": {
Type: schema.TypeSet,
Optional: true,
Expand Down Expand Up @@ -141,6 +147,8 @@ func resourceAuthMethodUniversalIdentityCreate(d *schema.ResourceData, m interfa
denyRotate := d.Get("deny_rotate").(bool)
denyInheritance := d.Get("deny_inheritance").(bool)
ttl := d.Get("ttl").(int)
uidExpirationEventAtSet := d.Get("uid_expiration_event_at").(*schema.Set)
uidExpirationEventAt := common.ExpandStringList(uidExpirationEventAtSet.List())
subClaimsSet := d.Get("audit_logs_claims").(*schema.Set)
subClaims := common.ExpandStringList(subClaimsSet.List())
deleteProtection := d.Get("delete_protection").(string)
Expand All @@ -161,6 +169,7 @@ func resourceAuthMethodUniversalIdentityCreate(d *schema.ResourceData, m interfa
common.GetAkeylessPtr(&body.DenyRotate, denyRotate)
common.GetAkeylessPtr(&body.DenyInheritance, denyInheritance)
common.GetAkeylessPtr(&body.Ttl, ttl)
common.GetAkeylessPtr(&body.UidExpirationEventAt, uidExpirationEventAt)
common.GetAkeylessPtr(&body.AuditLogsClaims, subClaims)
common.GetAkeylessPtr(&body.DeleteProtection, deleteProtection)

Expand Down Expand Up @@ -280,6 +289,20 @@ func resourceAuthMethodUniversalIdentityRead(d *schema.ResourceData, m interface
return err
}
}
if len(rOut.AccessInfo.UidExpirationEvents) > 0 {
vals := make([]string, 0, len(rOut.AccessInfo.UidExpirationEvents))
for _, ev := range rOut.AccessInfo.UidExpirationEvents {
if ev.PercentPassed != nil {
vals = append(vals, strconv.FormatInt(*ev.PercentPassed, 10))
}
}
if len(vals) > 0 {
err = d.Set("uid_expiration_event_at", vals)
if err != nil {
return err
}
}
}
if rOut.AccessInfo.AuditLogsClaims != nil {
err = d.Set("audit_logs_claims", rOut.AccessInfo.AuditLogsClaims)
if err != nil {
Expand Down Expand Up @@ -339,6 +362,8 @@ func resourceAuthMethodUniversalIdentityUpdate(d *schema.ResourceData, m interfa
denyRotate := d.Get("deny_rotate").(bool)
denyInheritance := d.Get("deny_inheritance").(bool)
ttl := d.Get("ttl").(int)
uidExpirationEventAtSet := d.Get("uid_expiration_event_at").(*schema.Set)
uidExpirationEventAt := common.ExpandStringList(uidExpirationEventAtSet.List())
subClaimsSet := d.Get("audit_logs_claims").(*schema.Set)
subClaims := common.ExpandStringList(subClaimsSet.List())
deleteProtection := d.Get("delete_protection").(string)
Expand All @@ -359,6 +384,7 @@ func resourceAuthMethodUniversalIdentityUpdate(d *schema.ResourceData, m interfa
common.GetAkeylessPtr(&body.DenyRotate, denyRotate)
common.GetAkeylessPtr(&body.DenyInheritance, denyInheritance)
common.GetAkeylessPtr(&body.Ttl, ttl)
common.GetAkeylessPtr(&body.UidExpirationEventAt, uidExpirationEventAt)
common.GetAkeylessPtr(&body.AuditLogsClaims, subClaims)
common.GetAkeylessPtr(&body.NewName, name)
common.GetAkeylessPtr(&body.DeleteProtection, deleteProtection)
Expand Down
173 changes: 173 additions & 0 deletions akeyless/resource_certificate_discovery.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
// generated file
package akeyless

import (
"context"
"fmt"
"strings"

akeyless_api "github.com/akeylesslabs/akeyless-go/v5"
"github.com/akeylesslabs/terraform-provider-akeyless/akeyless/common"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func resourceCertificateDiscovery() *schema.Resource {
Comment thread
tuvia-akeyless marked this conversation as resolved.
return &schema.Resource{
Description: "Certificate Discovery resource. Starts a certificate discovery scan and saves results under the target location. Destroying this resource removes it from Terraform state only and does not delete discovered certificates.",
Create: resourceCertificateDiscoveryCreate,
Read: resourceCertificateDiscoveryRead,
Delete: resourceCertificateDiscoveryDelete,
Importer: &schema.ResourceImporter{
State: resourceCertificateDiscoveryImport,
},
Schema: map[string]*schema.Schema{
"hosts": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "A comma separated list of IPs, CIDR ranges, or DNS names to scan",
},
"port_ranges": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Default: "443",
Description: "A comma separated list of port ranges. Example: 80,8080-8085",
},
"target_location": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "The results will be saved in this folder",
DiffSuppressFunc: common.DiffSuppressOnLeadingSlash,
},
"expiration_event_in": {
Type: schema.TypeSet,
Optional: true,
ForceNew: true,
Description: "How many days before the expiration of the certificate would you like to be notified. To specify multiple events, repeat this argument.",
Elem: &schema.Schema{Type: schema.TypeString},
},
Comment thread
tuvia-akeyless marked this conversation as resolved.
"protection_key": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Description: "The name of the key that protects the certificate value (if empty, the account default key will be used)",
},
"count_new": {
Type: schema.TypeInt,
Computed: true,
Description: "Number of new certificates discovered",
},
"count_existing": {
Type: schema.TypeInt,
Computed: true,
Description: "Number of existing certificates updated",
},
"count_hosts": {
Type: schema.TypeInt,
Computed: true,
Description: "Number of hosts scanned",
},
"count_failed": {
Type: schema.TypeInt,
Computed: true,
Description: "Number of failed scan targets",
},
"item_names": {
Type: schema.TypeList,
Computed: true,
Description: "Names of certificate items created or updated by the discovery",
Elem: &schema.Schema{Type: schema.TypeString},
},
},
}
}

func resourceCertificateDiscoveryCreate(d *schema.ResourceData, m interface{}) error {
provider := m.(*providerMeta)
client := *provider.client
token := *provider.token

ctx := context.Background()
hosts := strings.ReplaceAll(d.Get("hosts").(string), " ", "")
portRanges := strings.ReplaceAll(d.Get("port_ranges").(string), " ", "")
targetLocation := d.Get("target_location").(string)
expirationEventInSet := d.Get("expiration_event_in").(*schema.Set)
expirationEventIn := common.ExpandStringList(expirationEventInSet.List())
protectionKey := d.Get("protection_key").(string)

if hosts == "" {
return fmt.Errorf("hosts cannot be empty")
}

body := akeyless_api.CertificateDiscovery{
Hosts: hosts,
TargetLocation: targetLocation,
Token: &token,
}
common.GetAkeylessPtr(&body.PortRanges, portRanges)
common.GetAkeylessPtr(&body.ExpirationEventIn, expirationEventIn)
common.GetAkeylessPtr(&body.ProtectionKey, protectionKey)

out, resp, err := client.CertificateDiscovery(ctx).Body(body).Execute()
if err != nil {
return common.HandleError("can't run certificate discovery", resp, err)
}

countNew, countExisting, countHosts, countFailed := 0, 0, 0, 0
itemNames := []string{}
if out != nil && out.Results != nil {
results := out.Results
if results.CountNew != nil {
countNew = int(*results.CountNew)
}
if results.CountExisting != nil {
countExisting = int(*results.CountExisting)
}
if results.CountHosts != nil {
countHosts = int(*results.CountHosts)
}
if results.CountFailed != nil {
countFailed = int(*results.CountFailed)
}
if results.ItemNames != nil {
itemNames = results.ItemNames
}
}
if err := d.Set("count_new", countNew); err != nil {
return err
}
if err := d.Set("count_existing", countExisting); err != nil {
return err
}
if err := d.Set("count_hosts", countHosts); err != nil {
return err
}
if err := d.Set("count_failed", countFailed); err != nil {
return err
}
if err := d.Set("item_names", itemNames); err != nil {
return err
}

d.SetId(uuid.New().String())
return nil
}

func resourceCertificateDiscoveryRead(d *schema.ResourceData, m interface{}) error {
// Discovery is a one-shot scan with no get/describe API; retain Terraform state.
return nil
}

func resourceCertificateDiscoveryDelete(d *schema.ResourceData, m interface{}) error {
// Destroying the resource only removes it from Terraform state.
// Discovered certificate items are left intact.
d.SetId("")
return nil
}

func resourceCertificateDiscoveryImport(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) {
return nil, fmt.Errorf("certificate discovery cannot be imported because it is a one-shot scan with no remote identity")
}
Loading
Loading