dotnet / aspire

An opinionated, cloud ready stack for building observable, production ready, distributed applications in .NET
https://learn.microsoft.com/dotnet/aspire
MIT License
3.77k stars 439 forks source link

Introduce prompting behavior to inputs for Aspire manifests #1478

Closed mitchdenny closed 8 months ago

mitchdenny commented 10 months ago

In preview 2 we shipped the ability to tell the deployment tool the generate a random password for a particular resource, here is an example:

{
  "resources": {
    "postgresabstract": {
      "type": "container.v0",
      "image": "postgres:latest",
      "env": {
        "POSTGRES_HOST_AUTH_METHOD": "scram-sha-256",
        "POSTGRES_INITDB_ARGS": "--auth-host=scram-sha-256 --auth-local=scram-sha-256",
        "POSTGRES_PASSWORD": "{postgresabstract.inputs.password}"
      },
      "bindings": {
        "tcp": {
          "scheme": "tcp",
          "protocol": "tcp",
          "transport": "tcp",
          "containerPort": 5432
        }
      },
      "connectionString": "Host={postgresabstract.bindings.tcp.host};Port={postgresabstract.bindings.tcp.port};Username=postgres;Password={postgresabstract.inputs.password};",
      "inputs": {
        "password": {
          "type": "string",
          "secret": true,
          "default": {
            "generate": {
              "minLength": 10
            }
          }
        }
      }
    }
  }
}

Note the password input with the default value set to generate. Prompting would be the absence of a default, for example:

      "inputs": {
        "password": {
          "type": "string",
          "secret": true,
        }
      }

In this scenario the deployment tool would pause and prompt for the value. The deployment tool may persist the value and may provide a mechanism to provide the value in advance for CI/CD scenarios (both recommended).

To fine tune the prompt, an additional field would be added with the name "prompt" which would allow the prompt that is presented to the user to be fine-tuned.

      "inputs": {
        "openaikey": {
          "type": "string",
          "secret": true,
          "prompt": {
             "text": "Enter the Open AI API key."
          }
        }
      }

This is a simplistic example, but the prompt field could be expanded to support things like creating pick lists and simple validation rules. Some resource types which are intrinsically linked with a particular cloud (e.g. Azure OpenAI) might even have the ability to have a resource picker (with fallback behavior).

This particular feature will become important when introducing the concept of app wide secrets where a secret is shared between multiple services. In cases like this we might have a resource defined as follows:

{
  "resource": {
    "mysecretstore": {
      "type": "secret.store.v0"
    },
    "githubsharedsecret": {
      "type": "secret.value.v0",
      "value": "{githubsharedsecret.inputs.value}",
      "inputs": {
        "value": {
          "type": "string",
          "secret": true,
          "prompt": {
            "text": "Enter GitHub application shared secret"
          }
        }
      }
    }
  "webhookendpoint": {
    "type": "project.v0"
    "env": {
      "webhooksecret": "{githubsharedsecret.value}"
    },
    // Other properties omitted for brevity.
  }
  }
}

Here the deployment tool would notice that webhookendpoint (an app) references the shared secret, and the shared secret in turn defines an input field for its value. If deployed using a tool like azd this would result in a keyvault being created called mysecretstore containing a secret named githubsharedsecret with its value provided by the user when azd up is invoked.

The environment variable defined on the webhookendpoint project resource would be bound to keyvault using this mechanism.

Different target environments might have different analogues.

mitchdenny commented 10 months ago

/cc @davidfowl @ellismg

mitchdenny commented 10 months ago

Another dimension to these prompt mechanics is how they work for local development. Even though we don't generate the manifest for local execution, we do have requests coming in from folks who want to have some secret centrally managed which they share across their apps. Using builder.Configuration[...] is kind of clunky but works.

mitchdenny commented 9 months ago

Once the secrets work is done, azd should be able to do this. Putting this in preview 3 but I think the work left to do is on the AZD side.

Tracking issue: https://github.com/Azure/azure-dev/issues/3189

@ellismg its important that when the enhancements are made to handling the "inputs": field, that the behavior isn't limited to just secret resources.

ellismg commented 9 months ago

@ellismg its important that when the enhancements are made to handling the "inputs": field, that the behavior isn't limited to just secret resources.

Agree.

mitchdenny commented 8 months ago

This feature should work with any resource, but we will primarily use it with parameter.v0 resources.

mitchdenny commented 8 months ago

@ellismg do you have a mirror of this issue over in the azd repo.

ellismg commented 8 months ago

https://github.com/Azure/azure-dev/issues/3234