crossplane-contrib / provider-okta

Apache License 2.0
5 stars 7 forks source link

How to create a okta user with custom user-type #12

Open ebellani77 opened 2 months ago

ebellani77 commented 2 months ago

Hi guys, I try to create a user with a custom user-type using the following cr:

apiVersion: user.okta.upbound.io/v1alpha1
kind: User
metadata:
  name: example-user
spec:
  forProvider:
    email: exemple.user+crd@gmail.com
    firstName: Example
    lastName: User
    login: exemple.user+crd@gmail.com
    mobilePhone: "+390000000"
    department: "crossplane"
    userType: "customertype"
    customProfileAttributes: |
      {
        "apiKey": "",
        "tenantId": "b6917880-eb73-4bac-bbff-8f39c1f693ea",
        "entityId": "b6917880-eb73-4bac-bbff-8f39c1f693ea",
        "taxCode": "xxxxxxxxxxxx"
      }
  providerConfigRef:
    name: okta-provider-config

but the resource stuck with READY: Flase and SYNCED: true with the following error message:

status:
  atProvider: {}
  conditions:
  - lastTransitionTime: "2024-09-20T14:38:37Z"
    reason: Creating
    status: "False"
    type: Ready
  - lastTransitionTime: "2024-09-20T14:38:37Z"
    reason: ReconcileSuccess
    status: "True"
    type: Synced
  - lastTransitionTime: "2024-09-20T14:41:37Z"
    reason: Finished
    status: "True"
    type: AsyncOperation
  - lastTransitionTime: "2024-09-20T14:38:38Z"
    message: 'apply failed: failed to create user: the API returned an error: La convalida
      dell''API non è riuscita: newUser. Causes: errorSummary: Property name ''apiKey''
      is not defined in profile, errorSummary: Property name ''tenantId'' is not defined
      in profile, errorSummary: Property name ''entityId'' is not defined in profile,
      errorSummary: Property name ''taxCode'' is not defined in profile: '
    reason: ApplyFailure
    status: "False"
    type: LastAsyncOperation

Would you happen to have any suggestions?

rjop-hccgt commented 2 months ago

judging by the error it seams that your okta credentials are not properly setup, generally speaking you should have created a ProviderConfig Complete docs

apiVersion: okta.upbound.io/v1beta1
kind: ProviderConfig
metadata:
  name: okta-provider-config
spec:
  credentials:
    source: Secret
    secretRef:
      name: okta-creds # this can be anything
      namespace: crossplane-system # this can be anything
      key: credentials

If you are using a kubernetes secrets to hold your credentials it should be similar to what the terraform provider needs Example usage. Assuming you're using an api token it should be similar to or adjust to whatever your integration is needed:

{
  "base_url": "okta.com",
  "org_name": "<your org name>",
  "api_token": "<api_token>"
}
ebellani77 commented 2 months ago

Thank you for the suggestion, @rjop-hccgt, but I have successfully created other resource types in the correct organization with the current provider configuration. Could it be possible that I specified the userType name incorrectly?

I set the provider's log level to debug and observed the following messages:

2024-09-28T17:46:34Z    DEBUG   events  Waiting for external resource existence to be confirmed {"type": "Normal", "object": {"kind":"User","name":"example-user","uid":"30e55a0e-e4ee-4f1f-9a6d-162e226210eb","apiVersion":"user.okta.upbound.io/v1alpha1","resourceVersion":"4249032"}, "reason": "PendingExternalResource"}
2024-09-28T17:46:35Z    DEBUG   provider-okta   Reconciling {"controller": "managed/user.okta.upbound.io/v1alpha1, kind=user", "request": "/example-user"}
2024-09-28T17:46:35Z    DEBUG   provider-okta   Running terraform   {"workspace": "/tmp/30e55a0e-e4ee-4f1f-9a6d-162e226210eb", "args": ["apply", "-refresh-only", "-auto-approve", "-input=false", "-lock=false", "-json"]}
2024-09-28T17:46:36Z    DEBUG   provider-okta   refresh ended   {"workspace": "/tmp/30e55a0e-e4ee-4f1f-9a6d-162e226210eb", "out": "{\"@level\":\"info\",\"@message\":\"Terraform 1.REDACTED.7\",\"@module\":\"terraform.ui\",\"@timestamp\":\"2REDACTED24-REDACTED9-28T17:46:3REDACTED.997REDACTED39Z\",\"terraform\":\"1.REDACTED.7\",\"type\":\"version\",\"ui\":\"1.1\"}\n{\"@level\":\"info\",\"@message\":\"okta_user.example-user: Refreshing state...\",\"@module\":\"terraform.ui\",\"@timestamp\":\"2REDACTED24-REDACTED9-28T17:46:36.49876REDACTEDZ\",\"hook\":{\"resource\":{\"addr\":\"okta_user.example-user\",\"module\":\"\",\"resource\":\"okta_user.example-user\",\"implied_provider\":\"okta\",\"resource_type\":\"okta_user\",\"resource_name\":\"example-user\",\"resource_key\":null},\"id_key\":\"id\"},\"type\":\"refresh_start\"}\n{\"@level\":\"info\",\"@message\":\"okta_user.example-user: Refresh complete\",\"@module\":\"terraform.ui\",\"@timestamp\":\"2REDACTED24-REDACTED9-28T17:46:36.49974REDACTEDZ\",\"hook\":{\"resource\":{\"addr\":\"okta_user.example-user\",\"module\":\"\",\"resource\":\"okta_user.example-user\",\"implied_provider\":\"okta\",\"resource_type\":\"okta_user\",\"resource_name\":\"example-user\",\"resource_key\":null}},\"type\":\"refresh_complete\"}\n{\"@level\":\"info\",\"@message\":\"okta_user.example-user: Drift detected (delete)\",\"@module\":\"terraform.ui\",\"@timestamp\":\"2REDACTED24-REDACTED9-28T17:46:36.REDACTEDREDACTED247REDACTEDZ\",\"change\":{\"resource\":{\"addr\":\"okta_user.example-user\",\"module\":\"\",\"resource\":\"okta_user.example-user\",\"implied_provider\":\"okta\",\"resource_type\":\"okta_user\",\"resource_name\":\"example-user\",\"resource_key\":null},\"action\":\"delete\"},\"type\":\"resource_drift\"}\n{\"@level\":\"info\",\"@message\":\"Plan: REDACTED to add, REDACTED to change, REDACTED to destroy.\",\"@module\":\"terraform.ui\",\"@timestamp\":\"2REDACTED24-REDACTED9-28T17:46:36.REDACTEDREDACTED2REDACTED24Z\",\"changes\":{\"add\":REDACTED,\"change\":REDACTED,\"import\":REDACTED,\"remove\":REDACTED,\"operation\":\"plan\"},\"type\":\"change_summary\"}\n{\"@level\":\"info\",\"@message\":\"Apply complete! Resources: REDACTED added, REDACTED changed, REDACTED destroyed.\",\"@module\":\"terraform.ui\",\"@timestamp\":\"2REDACTED24-REDACTED9-28T17:46:36.REDACTEDREDACTED7REDACTED99Z\",\"changes\":{\"add\":REDACTED,\"change\":REDACTED,\"import\":REDACTED,\"remove\":REDACTED,\"operation\":\"apply\"},\"type\":\"change_summary\"}\n{\"@level\":\"info\",\"@message\":\"Outputs: REDACTED\",\"@module\":\"terraform.ui\",\"@timestamp\":\"2REDACTED24-REDACTED9-28T17:46:36.REDACTEDREDACTED7622Z\",\"outputs\":{},\"type\":\"outputs\"}\n"}
rjop-hccgt commented 2 months ago

@ebellani77 I would probably check Okta's log from the admin console, it seems that Okta is rejecting the creation for one reason or another, it seems that the YAML definition is correct and is being sent to okta.

ebellani77 commented 2 months ago

@rjop-hccgt The issue is probably related to the Okta Terraform provider as described here.

To check what is described in the issue I executed the following steps: 1- create a "normal" user using the yaml shown below:

metadata:
  name: example-user
spec:
  forProvider:
    email: exemple.user+crd@gmail.com
    firstName: Example
    lastName: User
    login: exemple.user+crd@gmail.com
    mobilePhone: "+390000000"
    department: "crossplane"
  providerConfigRef:
    name: okta-provider-config

2- I modified the type of the user directly on the Okta console; 3- I manually edited the cr created in step 1, adding the customProfileAttributes node:

  customProfileAttributes: |
        {
          "apiKey": "",
          "tenantId": "b6917880-eb73-4bac-bbff-8f39c1f693ea",
          "entityId": "b6917880-eb73-4bac-bbff-8f39c1f693ea",
          "taxCode": "XXXXXXXXXXX"
        }

And the magic happened, the resource before stuck, now results READY: true and SYNCED: true.

k get user.user.okta.upbound.io/example-user

NAME           READY   SYNCED   EXTERNAL-NAME          AGE
example-user   True    True     00uhfv5owh0CGDqmK417   14m

As a double-check, I used Okta APIs for each step mentioned above, and below is the result:

1- normal user creation:

{
    "id": "00uhfv5owh0CGDqmK417",
    "status": "PROVISIONED",
    "created": "2024-09-30T17:26:51.000Z",
    "activated": "2024-09-30T17:26:52.000Z",
    "statusChanged": "2024-09-30T17:26:52.000Z",
    "lastLogin": null,
    "lastUpdated": "2024-09-30T17:26:52.000Z",
    "passwordChanged": null,
    "type": {
        "id": "oty4rx53xra4WNBVG417"
    },
    "profile": {
        "firstName": "Example",
        "lastName": "User",
        "mobilePhone": "+390000000",
        "secondEmail": null,
        "department": "crossplane",
        "login": "exemple.user+crd@gmail.com",
        "email": "exemple.user+crd@gmail.com"
    },
    ...

2- Okta user type manually modified from oty4rx53xra4WNBVG417 to oty5l6wzges1rh8Ci417 :

{
    "id": "00uhfv5owh0CGDqmK417",
    "status": "PROVISIONED",
    "created": "2024-09-30T17:26:51.000Z",
    "activated": "2024-09-30T17:26:52.000Z",
    "statusChanged": "2024-09-30T17:26:52.000Z",
    "lastLogin": null,
    "lastUpdated": "2024-09-30T17:29:37.000Z",
    "passwordChanged": null,
    "type": {
        "id": "oty5l6wzges1rh8Ci417"
    },
    "profile": {
        "firstName": "Example",
        "lastName": "User",
        "mobilePhone": "+390000000",
        "secondEmail": null,
        "department": "crossplane",
        "login": "exemple.user+crd@gmail.com",
        "email": "exemple.user+crd@gmail.com"
    },
    ...

3- I manually edited the cr:

{
    "id": "00uhfv5owh0CGDqmK417",
    "status": "PROVISIONED",
    "created": "2024-09-30T17:26:51.000Z",
    "activated": "2024-09-30T17:26:52.000Z",
    "statusChanged": "2024-09-30T17:26:52.000Z",
    "lastLogin": null,
    "lastUpdated": "2024-09-30T17:35:14.000Z",
    "passwordChanged": null,
    "type": {
        "id": "oty5l6wzges1rh8Ci417"
    },
    "profile": {
        "firstName": "Example",
        "lastName": "User",
        "mobilePhone": "+390000000",
        "tenantId": "b6917880-eb73-4bac-bbff-8f39c1f693ea",
        "secondEmail": null,
        "entityId": "b6917880-eb73-4bac-bbff-8f39c1f693ea",
        "department": "crossplane",
        "taxCode": "XXXXXXXXXXX",
        "login": "exemple.user+crd@gmail.com",
        "email": "exemple.user+crd@gmail.com"
    },
   ... 

Finally, I checked the Terraform state inside the Crossplane provider pod and it appears as expected.

provider-okta-65e9777ed0e0-b947c555c-ssmtz:/tmp/c5f39e11-2e06-4d3e-864a-629a4978de7a$ cat terraform.tfstate

{
  "version": 4,
  "terraform_version": "1.5.7",
  "serial": 6,
  "lineage": "c5f39e11-2e06-4d3e-864a-629a4978de7a",
  "outputs": {},
  "resources": [
    {
      "mode": "managed",
      "type": "okta_user",
      "name": "example-user",
      "provider": "provider[\"registry.terraform.io/okta/okta\"]",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            "city": null,
            "cost_center": null,
            "country_code": null,
            "custom_profile_attributes": "{\"entityId\":\"b6917880-eb73-4bac-bbff-8f39c1f693ea\",\"taxCode\":\"XXXXXXXXXXX\",\"tenantId\":\"b6917880-eb73-4bac-bbff-8f39c1f693ea\"}",
            "custom_profile_attributes_to_ignore": null,
            "department": "crossplane",
            "display_name": null,
            "division": null,
            "email": "exemple.user+crd@gmail.com",
            "employee_number": null,
            "expire_password_on_create": false,
            "first_name": "Example",
            "honorific_prefix": null,
            "honorific_suffix": null,
            "id": "00uhfv5owh0CGDqmK417",
            "last_name": "User",
            "locale": null,
            "login": "exemple.user+crd@gmail.com",
            "manager": null,
            "manager_id": null,
            "middle_name": null,
            "mobile_phone": "+390000000",
            "nick_name": null,
            "old_password": null,
            "organization": null,
            "password": null,
            "password_hash": [],
            "password_inline_hook": null,
            "postal_address": null,
            "preferred_language": null,
            "primary_phone": null,
            "profile_url": null,
            "raw_status": "PROVISIONED",
            "recovery_answer": null,
            "recovery_question": null,
            "second_email": null,
            "skip_roles": false,
            "state": null,
            "status": "PROVISIONED",
            "street_address": null,
            "timezone": null,
            "title": null,
            "user_type": null,
            "zip_code": null
          },
          "sensitive_attributes": [],
          "private": "bnVsbA=="
        }
      ]
    }
  ],
  "check_results": null
}

Now, I have changed my focus to understanding how to fix the Okta terraform provider 🙂

ebellani77 commented 1 month ago

As a compendium, I found this issue on Terraform Okta provider repo, clearing any doubts.