Skip to content

Commit

Permalink
Add RolesAnywhere Profile resource
Browse files Browse the repository at this point in the history
  • Loading branch information
mattburgess committed Jul 18, 2022
1 parent 618bd8c commit 3868756
Show file tree
Hide file tree
Showing 7 changed files with 604 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/25850.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
aws_rolesanywhere_profile
```
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1825,6 +1825,7 @@ func Provider() *schema.Provider {

"aws_resourcegroups_group": resourcegroups.ResourceGroup(),

"aws_rolesanywhere_profile": rolesanywhere.ResourceProfile(),
"aws_rolesanywhere_trust_anchor": rolesanywhere.ResourceTrustAnchor(),

"aws_route53_delegation_set": route53.ResourceDelegationSet(),
Expand Down
26 changes: 26 additions & 0 deletions internal/service/rolesanywhere/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,32 @@ import (
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
)

func FindProfileByID(ctx context.Context, conn *rolesanywhere.Client, id string) (*types.ProfileDetail, error) {
in := &rolesanywhere.GetProfileInput{
ProfileId: aws.String(id),
}

out, err := conn.GetProfile(ctx, in)

var resourceNotFoundException *types.ResourceNotFoundException
if errors.As(err, &resourceNotFoundException) {
return nil, &resource.NotFoundError{
LastError: err,
LastRequest: in,
}
}

if err != nil {
return nil, err
}

if out == nil || out.Profile == nil {
return nil, tfresource.NewEmptyResultError(in)
}

return out.Profile, nil
}

func FindTrustAnchorByID(ctx context.Context, conn *rolesanywhere.Client, id string) (*types.TrustAnchorDetail, error) {
in := &rolesanywhere.GetTrustAnchorInput{
TrustAnchorId: aws.String(id),
Expand Down
13 changes: 13 additions & 0 deletions internal/service/rolesanywhere/flex.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package rolesanywhere

func expandStringList(tfList []interface{}) []string {
var result []string

for _, rawVal := range tfList {
if v, ok := rawVal.(string); ok && v != "" {
result = append(result, v)
}
}

return result
}
265 changes: 265 additions & 0 deletions internal/service/rolesanywhere/profile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
package rolesanywhere

import (
"context"
"errors"
"log"

"github.com/aws/aws-sdk-go-v2/service/rolesanywhere"
"github.com/aws/aws-sdk-go-v2/service/rolesanywhere/types"
"github.com/aws/aws-sdk-go/aws"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
"github.com/hashicorp/terraform-provider-aws/internal/verify"
)

func ResourceProfile() *schema.Resource {
return &schema.Resource{
CreateContext: resourceProfileCreate,
ReadContext: resourceProfileRead,
UpdateContext: resourceProfileUpdate,
DeleteContext: resourceProfileDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},

Schema: map[string]*schema.Schema{
"arn": {
Type: schema.TypeString,
Computed: true,
},
"duration_seconds": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"enabled": {
Type: schema.TypeBool,
Optional: true,
},
"managed_policy_arns": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"name": {
Type: schema.TypeString,
Required: true,
},
"require_instance_properties": {
Type: schema.TypeBool,
Optional: true,
},
"role_arns": {
Type: schema.TypeSet,
Required: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"session_policy": {
Type: schema.TypeString,
Optional: true,
},
"tags": tftags.TagsSchema(),
"tags_all": tftags.TagsSchemaComputed(),
},
CustomizeDiff: verify.SetTagsDiff,
}
}

func resourceProfileCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*conns.AWSClient).RolesAnywhereConn
defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig
tags := defaultTagsConfig.MergeTags(tftags.New(d.Get("tags").(map[string]interface{})))
name := d.Get("name").(string)

input := &rolesanywhere.CreateProfileInput{
Name: aws.String(name),
RoleArns: expandStringList(d.Get("role_arns").(*schema.Set).List()),
Tags: Tags(tags.IgnoreAWS()),
}

if v, ok := d.GetOk("duration_seconds"); ok {
input.DurationSeconds = aws.Int32(int32(v.(int)))
}

if v, ok := d.GetOk("enabled"); ok {
input.Enabled = aws.Bool(v.(bool))
}

if v, ok := d.GetOk("managed_policy_arns"); ok {
input.ManagedPolicyArns = expandStringList(v.(*schema.Set).List())
}

if v, ok := d.GetOk("require_instance_properties"); ok {
input.RequireInstanceProperties = aws.Bool(v.(bool))
}

if v, ok := d.GetOk("session_policy"); ok {
input.SessionPolicy = aws.String(v.(string))
}

log.Printf("[DEBUG] Creating RolesAnywhere Profile (%s): %#v", d.Id(), input)
output, err := conn.CreateProfile(ctx, input)

if err != nil {
return diag.Errorf("creating RolesAnywhere Profile (%s): %s", name, err)
}

d.SetId(aws.StringValue(output.Profile.ProfileId))

return resourceProfileRead(ctx, d, meta)
}

func resourceProfileRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*conns.AWSClient).RolesAnywhereConn
defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig
ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig

profile, err := FindProfileByID(ctx, conn, d.Id())

if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] RolesAnywhere Profile (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

if err != nil {
return diag.Errorf("reading RolesAnywhere Profile (%s): %s", d.Id(), err)
}

d.Set("arn", profile.ProfileArn)
d.Set("duration_seconds", profile.DurationSeconds)
d.Set("enabled", profile.Enabled)
d.Set("managed_policy_arns", profile.ManagedPolicyArns)
d.Set("name", profile.Name)
d.Set("require_instance_properties", profile.RequireInstanceProperties)
d.Set("role_arns", profile.RoleArns)
d.Set("session_policy", profile.SessionPolicy)

tags, err := ListTags(ctx, conn, d.Get("arn").(string))
if err != nil {
return diag.Errorf("listing tags for RolesAnywhere Profile (%s): %s", d.Id(), err)
}

tags = tags.IgnoreAWS().IgnoreConfig(ignoreTagsConfig)

//lintignore:AWSR002
if err := d.Set("tags", tags.RemoveDefaultConfig(defaultTagsConfig).Map()); err != nil {
return diag.Errorf("setting tags: %s", err)
}

if err := d.Set("tags_all", tags.Map()); err != nil {
return diag.Errorf("setting tags_all: %s", err)
}

return nil
}

func resourceProfileUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*conns.AWSClient).RolesAnywhereConn

if d.HasChangesExcept("enabled", "tags_all") {
input := &rolesanywhere.UpdateProfileInput{
ProfileId: aws.String(d.Id()),
}

if d.HasChange("duration_seconds") {
input.DurationSeconds = aws.Int32(int32(d.Get("duration_seconds").(int)))
}

if d.HasChange("managed_policy_arns") {
input.ManagedPolicyArns = expandStringList(d.Get("managed_policy_arns").(*schema.Set).List())
}

if d.HasChange("name") {
input.Name = aws.String(d.Get("name").(string))
}

if d.HasChange("role_arns") {
input.RoleArns = expandStringList(d.Get("role_arns").(*schema.Set).List())
}

if d.HasChange("session_policy") {
input.Name = aws.String(d.Get("session_policy").(string))
}

log.Printf("[DEBUG] Updating RolesAnywhere Profile (%s): %#v", d.Id(), input)
_, err := conn.UpdateProfile(ctx, input)
if err != nil {
return diag.Errorf("updating RolesAnywhere Profile (%s): %s", d.Id(), err)
}
}

if d.HasChange("enabled") {
_, n := d.GetChange("enabled")
if n == "true" {
err := enableProfile(ctx, d.Id(), meta)
if err != nil {
diag.Errorf("enabling RolesAnywhere Profile (%s): %s", d.Id(), err)
}
} else {
err := disableProfile(ctx, d.Id(), meta)
if err != nil {
diag.Errorf("disabling RolesAnywhere Profile (%s): %s", d.Id(), err)
}
}
}

if d.HasChange("tags_all") {
o, n := d.GetChange("tags_all")
if err := UpdateTags(ctx, conn, d.Get("arn").(string), o, n); err != nil {
return diag.Errorf("updating tags: %s", err)
}
}

return resourceProfileRead(ctx, d, meta)
}

func resourceProfileDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*conns.AWSClient).RolesAnywhereConn

log.Printf("[DEBUG] Deleting RolesAnywhere Profile (%s)", d.Id())
_, err := conn.DeleteProfile(ctx, &rolesanywhere.DeleteProfileInput{
ProfileId: aws.String(d.Id()),
})

var resourceNotFoundException *types.ResourceNotFoundException
if errors.As(err, &resourceNotFoundException) {
return nil
}

if err != nil {
return diag.Errorf("deleting RolesAnywhere Profile: (%s): %s", d.Id(), err)
}

return nil
}

func disableProfile(ctx context.Context, profileId string, meta interface{}) error {
conn := meta.(*conns.AWSClient).RolesAnywhereConn

input := &rolesanywhere.DisableProfileInput{
ProfileId: aws.String(profileId),
}

_, err := conn.DisableProfile(ctx, input)
return err
}

func enableProfile(ctx context.Context, profileId string, meta interface{}) error {
conn := meta.(*conns.AWSClient).RolesAnywhereConn

input := &rolesanywhere.EnableProfileInput{
ProfileId: aws.String(profileId),
}

_, err := conn.EnableProfile(ctx, input)
return err
}
Loading

0 comments on commit 3868756

Please sign in to comment.