@@ -92,6 +92,87 @@ with a common perimeter, but should not be able to share data among
9292themselves.` ,
9393 Default : "PERIMETER_TYPE_REGULAR" ,
9494 },
95+ "spec" : {
96+ Type : schema .TypeList ,
97+ Optional : true ,
98+ Description : `Proposed (or dry run) ServicePerimeter configuration.
99+ This configuration allows to specify and test ServicePerimeter configuration
100+ without enforcing actual access restrictions. Only allowed to be set when
101+ the 'useExplicitDryRunSpec' flag is set.` ,
102+ MaxItems : 1 ,
103+ Elem : & schema.Resource {
104+ Schema : map [string ]* schema.Schema {
105+ "access_levels" : {
106+ Type : schema .TypeList ,
107+ Optional : true ,
108+ Description : `A list of AccessLevel resource names that allow resources within
109+ the ServicePerimeter to be accessed from the internet.
110+ AccessLevels listed must be in the same policy as this
111+ ServicePerimeter. Referencing a nonexistent AccessLevel is a
112+ syntax error. If no AccessLevel names are listed, resources within
113+ the perimeter can only be accessed via GCP calls with request
114+ origins within the perimeter. For Service Perimeter Bridge, must
115+ be empty.
116+
117+ Format: accessPolicies/{policy_id}/accessLevels/{access_level_name}` ,
118+ Elem : & schema.Schema {
119+ Type : schema .TypeString ,
120+ },
121+ AtLeastOneOf : []string {"status.0.resources" , "status.0.access_levels" , "status.0.restricted_services" },
122+ },
123+ "resources" : {
124+ Type : schema .TypeList ,
125+ Optional : true ,
126+ Description : `A list of GCP resources that are inside of the service perimeter.
127+ Currently only projects are allowed.
128+ Format: projects/{project_number}` ,
129+ Elem : & schema.Schema {
130+ Type : schema .TypeString ,
131+ },
132+ AtLeastOneOf : []string {"status.0.resources" , "status.0.access_levels" , "status.0.restricted_services" },
133+ },
134+ "restricted_services" : {
135+ Type : schema .TypeList ,
136+ Optional : true ,
137+ Description : `GCP services that are subject to the Service Perimeter
138+ restrictions. Must contain a list of services. For example, if
139+ 'storage.googleapis.com' is specified, access to the storage
140+ buckets inside the perimeter must meet the perimeter's access
141+ restrictions.` ,
142+ Elem : & schema.Schema {
143+ Type : schema .TypeString ,
144+ },
145+ AtLeastOneOf : []string {"status.0.resources" , "status.0.access_levels" , "status.0.restricted_services" },
146+ },
147+ "vpc_accessible_services" : {
148+ Type : schema .TypeList ,
149+ Optional : true ,
150+ Description : `Specifies how APIs are allowed to communicate within the Service
151+ Perimeter.` ,
152+ MaxItems : 1 ,
153+ Elem : & schema.Resource {
154+ Schema : map [string ]* schema.Schema {
155+ "allowed_services" : {
156+ Type : schema .TypeList ,
157+ Optional : true ,
158+ Description : `The list of APIs usable within the Service Perimeter.
159+ Must be empty unless 'enableRestriction' is True.` ,
160+ Elem : & schema.Schema {
161+ Type : schema .TypeString ,
162+ },
163+ },
164+ "enable_restriction" : {
165+ Type : schema .TypeBool ,
166+ Optional : true ,
167+ Description : `Whether to restrict API calls within the Service Perimeter to the
168+ list of APIs specified in 'allowedServices'.` ,
169+ },
170+ },
171+ },
172+ },
173+ },
174+ },
175+ },
95176 "status" : {
96177 Type : schema .TypeList ,
97178 Optional : true ,
@@ -174,6 +255,19 @@ list of APIs specified in 'allowedServices'.`,
174255 },
175256 },
176257 },
258+ "use_explicit_dry_run_spec" : {
259+ Type : schema .TypeBool ,
260+ Optional : true ,
261+ Description : `Use explicit dry run spec flag. Ordinarily, a dry-run spec implicitly exists
262+ for all Service Perimeters, and that spec is identical to the status for those
263+ Service Perimeters. When this flag is set, it inhibits the generation of the
264+ implicit spec, thereby allowing the user to explicitly provide a
265+ configuration ("spec") to use in a dry-run version of the Service Perimeter.
266+ This allows the user to test changes to the enforced config ("status") without
267+ actually enforcing them. This testing is done through analyzing the differences
268+ between currently enforced and suggested restrictions. useExplicitDryRunSpec must
269+ bet set to True if any of the fields in the spec are set to non-default values.` ,
270+ },
177271 "create_time" : {
178272 Type : schema .TypeString ,
179273 Computed : true ,
@@ -216,6 +310,18 @@ func resourceAccessContextManagerServicePerimeterCreate(d *schema.ResourceData,
216310 } else if v , ok := d .GetOkExists ("status" ); ! isEmptyValue (reflect .ValueOf (statusProp )) && (ok || ! reflect .DeepEqual (v , statusProp )) {
217311 obj ["status" ] = statusProp
218312 }
313+ specProp , err := expandAccessContextManagerServicePerimeterSpec (d .Get ("spec" ), d , config )
314+ if err != nil {
315+ return err
316+ } else if v , ok := d .GetOkExists ("spec" ); ! isEmptyValue (reflect .ValueOf (specProp )) && (ok || ! reflect .DeepEqual (v , specProp )) {
317+ obj ["spec" ] = specProp
318+ }
319+ useExplicitDryRunSpecProp , err := expandAccessContextManagerServicePerimeterUseExplicitDryRunSpec (d .Get ("use_explicit_dry_run_spec" ), d , config )
320+ if err != nil {
321+ return err
322+ } else if v , ok := d .GetOkExists ("use_explicit_dry_run_spec" ); ! isEmptyValue (reflect .ValueOf (useExplicitDryRunSpecProp )) && (ok || ! reflect .DeepEqual (v , useExplicitDryRunSpecProp )) {
323+ obj ["useExplicitDryRunSpec" ] = useExplicitDryRunSpecProp
324+ }
219325 parentProp , err := expandAccessContextManagerServicePerimeterParent (d .Get ("parent" ), d , config )
220326 if err != nil {
221327 return err
@@ -318,6 +424,12 @@ func resourceAccessContextManagerServicePerimeterRead(d *schema.ResourceData, me
318424 if err := d .Set ("status" , flattenAccessContextManagerServicePerimeterStatus (res ["status" ], d , config )); err != nil {
319425 return fmt .Errorf ("Error reading ServicePerimeter: %s" , err )
320426 }
427+ if err := d .Set ("spec" , flattenAccessContextManagerServicePerimeterSpec (res ["spec" ], d , config )); err != nil {
428+ return fmt .Errorf ("Error reading ServicePerimeter: %s" , err )
429+ }
430+ if err := d .Set ("use_explicit_dry_run_spec" , flattenAccessContextManagerServicePerimeterUseExplicitDryRunSpec (res ["useExplicitDryRunSpec" ], d , config )); err != nil {
431+ return fmt .Errorf ("Error reading ServicePerimeter: %s" , err )
432+ }
321433 if err := d .Set ("name" , flattenAccessContextManagerServicePerimeterName (res ["name" ], d , config )); err != nil {
322434 return fmt .Errorf ("Error reading ServicePerimeter: %s" , err )
323435 }
@@ -347,6 +459,18 @@ func resourceAccessContextManagerServicePerimeterUpdate(d *schema.ResourceData,
347459 } else if v , ok := d .GetOkExists ("status" ); ! isEmptyValue (reflect .ValueOf (v )) && (ok || ! reflect .DeepEqual (v , statusProp )) {
348460 obj ["status" ] = statusProp
349461 }
462+ specProp , err := expandAccessContextManagerServicePerimeterSpec (d .Get ("spec" ), d , config )
463+ if err != nil {
464+ return err
465+ } else if v , ok := d .GetOkExists ("spec" ); ! isEmptyValue (reflect .ValueOf (v )) && (ok || ! reflect .DeepEqual (v , specProp )) {
466+ obj ["spec" ] = specProp
467+ }
468+ useExplicitDryRunSpecProp , err := expandAccessContextManagerServicePerimeterUseExplicitDryRunSpec (d .Get ("use_explicit_dry_run_spec" ), d , config )
469+ if err != nil {
470+ return err
471+ } else if v , ok := d .GetOkExists ("use_explicit_dry_run_spec" ); ! isEmptyValue (reflect .ValueOf (v )) && (ok || ! reflect .DeepEqual (v , useExplicitDryRunSpecProp )) {
472+ obj ["useExplicitDryRunSpec" ] = useExplicitDryRunSpecProp
473+ }
350474
351475 obj , err = resourceAccessContextManagerServicePerimeterEncoder (d , meta , obj )
352476 if err != nil {
@@ -379,6 +503,14 @@ func resourceAccessContextManagerServicePerimeterUpdate(d *schema.ResourceData,
379503 if d .HasChange ("status" ) {
380504 updateMask = append (updateMask , "status" )
381505 }
506+
507+ if d .HasChange ("spec" ) {
508+ updateMask = append (updateMask , "spec" )
509+ }
510+
511+ if d .HasChange ("use_explicit_dry_run_spec" ) {
512+ updateMask = append (updateMask , "useExplicitDryRunSpec" )
513+ }
382514 // updateMask is a URL parameter but not present in the schema, so replaceVars
383515 // won't set it
384516 url , err = addQueryParams (url , map [string ]string {"updateMask" : strings .Join (updateMask , "," )})
@@ -536,6 +668,64 @@ func flattenAccessContextManagerServicePerimeterStatusVPCAccessibleServicesAllow
536668 return schema .NewSet (schema .HashString , v .([]interface {}))
537669}
538670
671+ func flattenAccessContextManagerServicePerimeterSpec (v interface {}, d * schema.ResourceData , config * Config ) interface {} {
672+ if v == nil {
673+ return nil
674+ }
675+ original := v .(map [string ]interface {})
676+ if len (original ) == 0 {
677+ return nil
678+ }
679+ transformed := make (map [string ]interface {})
680+ transformed ["resources" ] =
681+ flattenAccessContextManagerServicePerimeterSpecResources (original ["resources" ], d , config )
682+ transformed ["access_levels" ] =
683+ flattenAccessContextManagerServicePerimeterSpecAccessLevels (original ["accessLevels" ], d , config )
684+ transformed ["restricted_services" ] =
685+ flattenAccessContextManagerServicePerimeterSpecRestrictedServices (original ["restrictedServices" ], d , config )
686+ transformed ["vpc_accessible_services" ] =
687+ flattenAccessContextManagerServicePerimeterSpecVPCAccessibleServices (original ["vpcAccessibleServices" ], d , config )
688+ return []interface {}{transformed }
689+ }
690+ func flattenAccessContextManagerServicePerimeterSpecResources (v interface {}, d * schema.ResourceData , config * Config ) interface {} {
691+ return v
692+ }
693+
694+ func flattenAccessContextManagerServicePerimeterSpecAccessLevels (v interface {}, d * schema.ResourceData , config * Config ) interface {} {
695+ return v
696+ }
697+
698+ func flattenAccessContextManagerServicePerimeterSpecRestrictedServices (v interface {}, d * schema.ResourceData , config * Config ) interface {} {
699+ return v
700+ }
701+
702+ func flattenAccessContextManagerServicePerimeterSpecVPCAccessibleServices (v interface {}, d * schema.ResourceData , config * Config ) interface {} {
703+ if v == nil {
704+ return nil
705+ }
706+ original := v .(map [string ]interface {})
707+ if len (original ) == 0 {
708+ return nil
709+ }
710+ transformed := make (map [string ]interface {})
711+ transformed ["enable_restriction" ] =
712+ flattenAccessContextManagerServicePerimeterSpecVPCAccessibleServicesEnableRestriction (original ["enableRestriction" ], d , config )
713+ transformed ["allowed_services" ] =
714+ flattenAccessContextManagerServicePerimeterSpecVPCAccessibleServicesAllowedServices (original ["allowedServices" ], d , config )
715+ return []interface {}{transformed }
716+ }
717+ func flattenAccessContextManagerServicePerimeterSpecVPCAccessibleServicesEnableRestriction (v interface {}, d * schema.ResourceData , config * Config ) interface {} {
718+ return v
719+ }
720+
721+ func flattenAccessContextManagerServicePerimeterSpecVPCAccessibleServicesAllowedServices (v interface {}, d * schema.ResourceData , config * Config ) interface {} {
722+ return v
723+ }
724+
725+ func flattenAccessContextManagerServicePerimeterUseExplicitDryRunSpec (v interface {}, d * schema.ResourceData , config * Config ) interface {} {
726+ return v
727+ }
728+
539729func flattenAccessContextManagerServicePerimeterName (v interface {}, d * schema.ResourceData , config * Config ) interface {} {
540730 return v
541731}
@@ -640,6 +830,96 @@ func expandAccessContextManagerServicePerimeterStatusVPCAccessibleServicesAllowe
640830 return v , nil
641831}
642832
833+ func expandAccessContextManagerServicePerimeterSpec (v interface {}, d TerraformResourceData , config * Config ) (interface {}, error ) {
834+ l := v .([]interface {})
835+ if len (l ) == 0 || l [0 ] == nil {
836+ return nil , nil
837+ }
838+ raw := l [0 ]
839+ original := raw .(map [string ]interface {})
840+ transformed := make (map [string ]interface {})
841+
842+ transformedResources , err := expandAccessContextManagerServicePerimeterSpecResources (original ["resources" ], d , config )
843+ if err != nil {
844+ return nil , err
845+ } else if val := reflect .ValueOf (transformedResources ); val .IsValid () && ! isEmptyValue (val ) {
846+ transformed ["resources" ] = transformedResources
847+ }
848+
849+ transformedAccessLevels , err := expandAccessContextManagerServicePerimeterSpecAccessLevels (original ["access_levels" ], d , config )
850+ if err != nil {
851+ return nil , err
852+ } else if val := reflect .ValueOf (transformedAccessLevels ); val .IsValid () && ! isEmptyValue (val ) {
853+ transformed ["accessLevels" ] = transformedAccessLevels
854+ }
855+
856+ transformedRestrictedServices , err := expandAccessContextManagerServicePerimeterSpecRestrictedServices (original ["restricted_services" ], d , config )
857+ if err != nil {
858+ return nil , err
859+ } else if val := reflect .ValueOf (transformedRestrictedServices ); val .IsValid () && ! isEmptyValue (val ) {
860+ transformed ["restrictedServices" ] = transformedRestrictedServices
861+ }
862+
863+ transformedVPCAccessibleServices , err := expandAccessContextManagerServicePerimeterSpecVPCAccessibleServices (original ["vpc_accessible_services" ], d , config )
864+ if err != nil {
865+ return nil , err
866+ } else if val := reflect .ValueOf (transformedVPCAccessibleServices ); val .IsValid () && ! isEmptyValue (val ) {
867+ transformed ["vpcAccessibleServices" ] = transformedVPCAccessibleServices
868+ }
869+
870+ return transformed , nil
871+ }
872+
873+ func expandAccessContextManagerServicePerimeterSpecResources (v interface {}, d TerraformResourceData , config * Config ) (interface {}, error ) {
874+ return v , nil
875+ }
876+
877+ func expandAccessContextManagerServicePerimeterSpecAccessLevels (v interface {}, d TerraformResourceData , config * Config ) (interface {}, error ) {
878+ return v , nil
879+ }
880+
881+ func expandAccessContextManagerServicePerimeterSpecRestrictedServices (v interface {}, d TerraformResourceData , config * Config ) (interface {}, error ) {
882+ return v , nil
883+ }
884+
885+ func expandAccessContextManagerServicePerimeterSpecVPCAccessibleServices (v interface {}, d TerraformResourceData , config * Config ) (interface {}, error ) {
886+ l := v .([]interface {})
887+ if len (l ) == 0 || l [0 ] == nil {
888+ return nil , nil
889+ }
890+ raw := l [0 ]
891+ original := raw .(map [string ]interface {})
892+ transformed := make (map [string ]interface {})
893+
894+ transformedEnableRestriction , err := expandAccessContextManagerServicePerimeterSpecVPCAccessibleServicesEnableRestriction (original ["enable_restriction" ], d , config )
895+ if err != nil {
896+ return nil , err
897+ } else if val := reflect .ValueOf (transformedEnableRestriction ); val .IsValid () && ! isEmptyValue (val ) {
898+ transformed ["enableRestriction" ] = transformedEnableRestriction
899+ }
900+
901+ transformedAllowedServices , err := expandAccessContextManagerServicePerimeterSpecVPCAccessibleServicesAllowedServices (original ["allowed_services" ], d , config )
902+ if err != nil {
903+ return nil , err
904+ } else if val := reflect .ValueOf (transformedAllowedServices ); val .IsValid () && ! isEmptyValue (val ) {
905+ transformed ["allowedServices" ] = transformedAllowedServices
906+ }
907+
908+ return transformed , nil
909+ }
910+
911+ func expandAccessContextManagerServicePerimeterSpecVPCAccessibleServicesEnableRestriction (v interface {}, d TerraformResourceData , config * Config ) (interface {}, error ) {
912+ return v , nil
913+ }
914+
915+ func expandAccessContextManagerServicePerimeterSpecVPCAccessibleServicesAllowedServices (v interface {}, d TerraformResourceData , config * Config ) (interface {}, error ) {
916+ return v , nil
917+ }
918+
919+ func expandAccessContextManagerServicePerimeterUseExplicitDryRunSpec (v interface {}, d TerraformResourceData , config * Config ) (interface {}, error ) {
920+ return v , nil
921+ }
922+
643923func expandAccessContextManagerServicePerimeterParent (v interface {}, d TerraformResourceData , config * Config ) (interface {}, error ) {
644924 return v , nil
645925}
0 commit comments