Skip to content

Commit 6930346

Browse files
Benito VisoneGiuMontesanogithub-actions[bot]
authored
feat: add same IDP feature flag (#752)
* feat: add DynamoDB table LastIDPUsed * feat: add last_idp_used_table variable and update configurations in all environments * terraform-docs: automated action * fix: update range key for LastIDPUsed DynamoDB table from clientId to id * feat: add LastIDPUsed DynamoDB table ARN and update IAM policies * terraform-docs: automated action * fix: update output reference for Last IDP Used DynamoDB table ARN * feat: add LastIDPUsed Connector and Model layer * feat: add sameIdp logic to Controller and Service layers * fix: ClientExtended constructor * fix: add last_idp_used_table_name configuration into application.properties * fix: unsupported time unit months changed to days * fix: add entityid parameter to LastIDPUSend entry * fix: sameIdp update logic * terraform-docs: automated action * tests: update tests including sameIdp claim logic * fix: same idp claim * chore: terraform fmt * fix: required last_idp_used_table variable * feat: hash id * feat: set last idp used timestamp ttl to 2 years * feat: add required_same_idp property to ClientRegistration OpenAPI schema --------- Co-authored-by: GiuMontesano <giuseppe.montesano@pagopa.it> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 81b8bc6 commit 6930346

File tree

38 files changed

+553
-45
lines changed

38 files changed

+553
-45
lines changed

src/infra/api/oi.tpl.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2754,6 +2754,11 @@
27542754
"familyName",
27552755
"fiscalNumber"
27562756
]
2757+
},
2758+
"required_same_idp": {
2759+
"type": "boolean",
2760+
"description": "If true, the client will get a claim called 'sameIdp' which will contain true if the IDP does not change between two consecutive logins. This is useful for clients that want to know if the user has changed IDP.",
2761+
"default": false
27572762
}
27582763
}
27592764
},

src/infra/dev/eu-south-1/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,21 +151,24 @@
151151
| <a name="input_aws_region"></a> [aws\_region](#input\_aws\_region) | AWS region to create resources. Default Milan | `string` | `"eu-south-1"` | no |
152152
| <a name="input_aws_region_short"></a> [aws\_region\_short](#input\_aws\_region\_short) | AWS region short format. | `string` | `"es-1"` | no |
153153
| <a name="input_cie_entity_id"></a> [cie\_entity\_id](#input\_cie\_entity\_id) | n/a | `string` | `"https://preproduzione.idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"` | no |
154+
| <a name="input_client_ids"></a> [client\_ids](#input\_client\_ids) | n/a | `list(string)` | <pre>[<br> "bxMiPVktuZ5lBNbZYJ3ODosXL57ltrLp7BgyOkw-0v4"<br>]</pre> | no |
154155
| <a name="input_client_registrations_table"></a> [client\_registrations\_table](#input\_client\_registrations\_table) | Client configurations table. | <pre>object({<br> point_in_time_recovery_enabled = optional(bool, false)<br> })</pre> | <pre>{<br> "point_in_time_recovery_enabled": false<br>}</pre> | no |
155156
| <a name="input_client_status_history_table"></a> [client\_status\_history\_table](#input\_client\_status\_history\_table) | Client Status History configurations table. | <pre>object({<br> point_in_time_recovery_enabled = optional(bool, false)<br> })</pre> | <pre>{<br> "point_in_time_recovery_enabled": false<br>}</pre> | no |
156157
| <a name="input_dlq_alarms"></a> [dlq\_alarms](#input\_dlq\_alarms) | n/a | <pre>object({<br> metric_name = string<br> namespace = string<br> threshold = optional(number)<br> evaluation_periods = optional(number)<br> period = optional(number)<br> statistic = optional(string)<br> comparison_operator = optional(string)<br> sns_topic_alarm_arn = optional(list(string))<br> })</pre> | <pre>{<br> "comparison_operator": "GreaterThanThreshold",<br> "evaluation_periods": 2,<br> "metric_name": "ApproximateNumberOfMessagesVisible",<br> "namespace": "AWS/SQS",<br> "period": 300,<br> "statistic": "Sum",<br> "threshold": 0<br>}</pre> | no |
157158
| <a name="input_dlq_assertion_setting"></a> [dlq\_assertion\_setting](#input\_dlq\_assertion\_setting) | n/a | <pre>object({<br> maximum_retry_attempts = number<br> maximum_record_age_in_seconds = number<br> })</pre> | <pre>{<br> "maximum_record_age_in_seconds": 259200,<br> "maximum_retry_attempts": 3<br>}</pre> | no |
158159
| <a name="input_dns_record_ttl"></a> [dns\_record\_ttl](#input\_dns\_record\_ttl) | Dns record ttl (in sec) | `number` | `3600` | no |
159160
| <a name="input_ecs_alarms"></a> [ecs\_alarms](#input\_ecs\_alarms) | n/a | <pre>map(object({<br> metric_name = string<br> namespace = string<br> threshold = number<br> evaluation_periods = number<br> period = number<br> statistic = string<br> comparison_operator = string<br> scaling_policy = optional(string, null)<br><br> }))</pre> | <pre>{<br> "cpu_high": {<br> "comparison_operator": "GreaterThanOrEqualToThreshold",<br> "evaluation_periods": 1,<br> "metric_name": "CPUUtilization",<br> "namespace": "AWS/ECS",<br> "period": 60,<br> "scaling_policy": "cpu_high",<br> "statistic": "Average",<br> "threshold": 50<br> },<br> "cpu_low": {<br> "comparison_operator": "LessThanOrEqualToThreshold",<br> "evaluation_periods": 3,<br> "metric_name": "CPUUtilization",<br> "namespace": "AWS/ECS",<br> "period": 900,<br> "scaling_policy": "cpu_low",<br> "statistic": "Average",<br> "threshold": 20<br> },<br> "mem_high": {<br> "comparison_operator": "GreaterThanOrEqualToThreshold",<br> "evaluation_periods": 1,<br> "metric_name": "MemoryUtilization",<br> "namespace": "AWS/ECS",<br> "period": 60,<br> "statistic": "Average",<br> "threshold": 70<br> }<br>}</pre> | no |
160-
| <a name="input_ecs_enable_container_insights"></a> [ecs\_enable\_container\_insights](#input\_ecs\_enable\_container\_insights) | Enable ecs cluster container inight. | `bool` | `false` | no |
161+
| <a name="input_ecs_enable_container_insights"></a> [ecs\_enable\_container\_insights](#input\_ecs\_enable\_container\_insights) | Enable ecs cluster container insight. | `bool` | `false` | no |
161162
| <a name="input_ecs_oneid_core"></a> [ecs\_oneid\_core](#input\_ecs\_oneid\_core) | Oneidentity core backend configurations. | <pre>object({<br> image_version = string<br> cpu = number<br> memory = number<br> container_cpu = number<br> container_memory = number<br> autoscaling = object({<br> enable = bool<br> desired_count = number<br> min_capacity = number<br> max_capacity = number<br> })<br> logs_retention_days = number<br> app_spid_test_enabled = optional(bool, false)<br> })</pre> | <pre>{<br> "app_spid_test_enabled": true,<br> "autoscaling": {<br> "desired_count": 1,<br> "enable": true,<br> "max_capacity": 2,<br> "min_capacity": 1<br> },<br> "container_cpu": 512,<br> "container_memory": 1024,<br> "cpu": 512,<br> "image_version": "ee2f581bd28b21011b9abb9fa98b4dd59b5ae4a9",<br> "logs_retention_days": 30,<br> "memory": 1024<br>}</pre> | no |
162163
| <a name="input_enable_nat_gateway"></a> [enable\_nat\_gateway](#input\_enable\_nat\_gateway) | Create nat gateway(s) | `bool` | `true` | no |
164+
| <a name="input_entity_id"></a> [entity\_id](#input\_entity\_id) | n/a | `list(string)` | <pre>[<br> "https://demo.spid.gov.it",<br> "https://validator.spid.gov.it",<br> "https://validator.dev.oneid.pagopa.it",<br> "https://5ucp2co2zvqle6tcyrx4i5se7q0xdkni.lambda-url.eu-south-1.on.aws",<br> "https://validator.dev.oneid.pagopa.it/demo",<br> "https://koz3yhpkscymaqgp4m7ceguu6m0tffuz.lambda-url.eu-south-1.on.aws",<br> "https://collaudo.idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO",<br> "https://preproduzione.idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"<br>]</pre> | no |
163165
| <a name="input_env_short"></a> [env\_short](#input\_env\_short) | Environment short. | `string` | `"d"` | no |
164166
| <a name="input_idp_metadata_table"></a> [idp\_metadata\_table](#input\_idp\_metadata\_table) | IDP Metadata configurations table. | <pre>object({<br> point_in_time_recovery_enabled = optional(bool, false)<br> })</pre> | <pre>{<br> "point_in_time_recovery_enabled": false<br>}</pre> | no |
165167
| <a name="input_idp_status_history_table"></a> [idp\_status\_history\_table](#input\_idp\_status\_history\_table) | IDP Status History configurations table. | <pre>object({<br> point_in_time_recovery_enabled = optional(bool, false)<br> })</pre> | <pre>{<br> "point_in_time_recovery_enabled": false<br>}</pre> | no |
166168
| <a name="input_is_gh_sns_arn"></a> [is\_gh\_sns\_arn](#input\_is\_gh\_sns\_arn) | n/a | `string` | `null` | no |
167169
| <a name="input_lambda_alarms"></a> [lambda\_alarms](#input\_lambda\_alarms) | n/a | <pre>map(object({<br> metric_name = optional(string, "Errors")<br> namespace = optional(string, "AWS/Lambda")<br> threshold = optional(number, 1)<br> evaluation_periods = optional(number, 1)<br> period = optional(number, 300)<br> statistic = optional(string, "Sum")<br> comparison_operator = optional(string, "GreaterThanOrEqualToThreshold")<br> treat_missing_data = optional(string, "notBreaching")<br> }))</pre> | <pre>{<br> "oneid-es-1-d-assertion": {},<br> "oneid-es-1-d-client-registration": {},<br> "oneid-es-1-d-metadata": {},<br> "oneid-es-1-d-update-idp-metadata": {}<br>}</pre> | no |
168170
| <a name="input_lambda_cloudwatch_logs_retention_in_days"></a> [lambda\_cloudwatch\_logs\_retention\_in\_days](#input\_lambda\_cloudwatch\_logs\_retention\_in\_days) | Cloudwatch log group retention days. | `number` | `14` | no |
171+
| <a name="input_last_idp_used_table"></a> [last\_idp\_used\_table](#input\_last\_idp\_used\_table) | Last IDP used table configurations. | <pre>object({<br> point_in_time_recovery_enabled = optional(bool, false)<br> })</pre> | <pre>{<br> "point_in_time_recovery_enabled": false<br>}</pre> | no |
169172
| <a name="input_metadata_info"></a> [metadata\_info](#input\_metadata\_info) | # Metadata Info variables## | <pre>object({<br> acs_url = string<br> slo_url = string<br> })</pre> | <pre>{<br> "acs_url": "/saml/acs",<br> "slo_url": "/saml/slo"<br>}</pre> | no |
170173
| <a name="input_number_of_images_to_keep"></a> [number\_of\_images\_to\_keep](#input\_number\_of\_images\_to\_keep) | Number of images to keeps in ECR. | `number` | `5` | no |
171174
| <a name="input_r53_dns_zone"></a> [r53\_dns\_zone](#input\_r53\_dns\_zone) | # R53 DNS zone ## | <pre>object({<br> name = string<br> comment = string<br> })</pre> | <pre>{<br> "comment": "Oneidentity dev zone.",<br> "name": "dev.oneid.pagopa.it"<br>}</pre> | no |

src/infra/dev/eu-south-1/main.tf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ module "backend" {
281281
dynamodb_clients_table_stream_arn = module.database.dynamodb_clients_table_stream_arn
282282
dynamodb_table_stream_registrations_arn = module.database.dynamodb_clients_table_stream_arn
283283
dynamodb_table_stream_arn = module.database.dynamodb_table_stream_arn
284+
table_last_idp_used_arn = module.database.table_last_idp_used_arn
284285
eventbridge_pipe_sessions = {
285286
pipe_name = format("%s-sessions-pipe", local.project)
286287
kms_sessions_table_alias = module.database.kms_sessions_table_alias_arn
@@ -481,6 +482,7 @@ module "database" {
481482
idp_metadata_table = var.idp_metadata_table
482483
idp_status_history_table = var.idp_status_history_table
483484
client_status_history_table = var.client_status_history_table
485+
last_idp_used_table = var.last_idp_used_table
484486
idp_entity_ids = local.idp_entity_ids
485487
clients = local.clients
486488
}

src/infra/dev/eu-south-1/variables.tf

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ variable "r53_dns_zone" {
8686
## ECS Cluster ##
8787
variable "ecs_enable_container_insights" {
8888
type = bool
89-
description = "Enable ecs cluster container inight."
89+
description = "Enable ecs cluster container insight."
9090
default = false
9191
}
9292

@@ -236,6 +236,16 @@ variable "client_status_history_table" {
236236
}
237237
}
238238

239+
variable "last_idp_used_table" {
240+
type = object({
241+
point_in_time_recovery_enabled = optional(bool, false)
242+
})
243+
description = "Last IDP used table configurations."
244+
default = {
245+
point_in_time_recovery_enabled = false
246+
}
247+
}
248+
239249
variable "cie_entity_id" {
240250
type = string
241251
default = "https://preproduzione.idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"
@@ -667,3 +677,22 @@ variable "api_alarms" {
667677
},
668678
}
669679
}
680+
681+
variable "entity_id" {
682+
type = list(string)
683+
default = [
684+
"https://demo.spid.gov.it",
685+
"https://validator.spid.gov.it",
686+
"https://validator.dev.oneid.pagopa.it",
687+
"https://5ucp2co2zvqle6tcyrx4i5se7q0xdkni.lambda-url.eu-south-1.on.aws",
688+
"https://validator.dev.oneid.pagopa.it/demo",
689+
"https://koz3yhpkscymaqgp4m7ceguu6m0tffuz.lambda-url.eu-south-1.on.aws",
690+
"https://collaudo.idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO",
691+
"https://preproduzione.idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"
692+
]
693+
}
694+
695+
variable "client_ids" {
696+
type = list(string)
697+
default = ["bxMiPVktuZ5lBNbZYJ3ODosXL57ltrLp7BgyOkw-0v4"]
698+
}

src/infra/modules/backend/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@
262262
| <a name="input_ssm_cert_key"></a> [ssm\_cert\_key](#input\_ssm\_cert\_key) | TODO fix name | <pre>object({<br> cert_pem = optional(string, "cert.pem")<br> key_pem = optional(string, "key.pem")<br> })</pre> | n/a | yes |
263263
| <a name="input_switch_region_enabled"></a> [switch\_region\_enabled](#input\_switch\_region\_enabled) | n/a | `bool` | `false` | no |
264264
| <a name="input_table_client_registrations_arn"></a> [table\_client\_registrations\_arn](#input\_table\_client\_registrations\_arn) | Dynamodb table client registrations arn. | `string` | n/a | yes |
265+
| <a name="input_table_last_idp_used_arn"></a> [table\_last\_idp\_used\_arn](#input\_table\_last\_idp\_used\_arn) | Dynamodb table Last IDP used arn. | `string` | n/a | yes |
265266
| <a name="input_update_status_lambda"></a> [update\_status\_lambda](#input\_update\_status\_lambda) | n/a | <pre>object({<br> name = string<br> filename = string<br> assets_bucket_arn = string<br> cloudwatch_logs_retention_in_days = string<br> environment_variables = map(string)<br> vpc_s3_prefix_id = string<br> vpc_endpoint_dynamodb_prefix_id = string<br> vpc_subnet_ids = list(string)<br> vpc_id = string<br> })</pre> | n/a | yes |
266267
| <a name="input_vpc_cidr_block"></a> [vpc\_cidr\_block](#input\_vpc\_cidr\_block) | VPC cidr block. | `string` | n/a | yes |
267268
| <a name="input_vpc_id"></a> [vpc\_id](#input\_vpc\_id) | VPC id | `string` | n/a | yes |

src/infra/modules/backend/ecs.tf

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,18 @@ resource "aws_iam_policy" "ecs_core_task" {
141141
"${var.table_client_registrations_arn}"
142142
]
143143
},
144+
{
145+
Sid = "DynamoDBLastIDPUsedRW"
146+
Effect = "Allow"
147+
Action = [
148+
"dynamodb:GetItem",
149+
"dynamodb:PutItem",
150+
"dynamodb:UpdateItem",
151+
]
152+
Resource = [
153+
"${var.table_last_idp_used_arn}"
154+
]
155+
},
144156
{
145157
Sid = "KSMSign"
146158
Effect = "Allow"

src/infra/modules/backend/variables.tf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,11 @@ variable "client_registration_lambda" {
178178

179179
}
180180

181+
variable "table_last_idp_used_arn" {
182+
type = string
183+
description = "Dynamodb table Last IDP used arn."
184+
}
185+
181186
variable "metadata_lambda" {
182187
type = object({
183188
name = string

0 commit comments

Comments
 (0)