diff --git a/doc/api/integrations.md b/doc/api/integrations.md index 90bb26ffd3d..c1564826944 100644 --- a/doc/api/integrations.md +++ b/doc/api/integrations.md @@ -315,14 +315,15 @@ PUT /projects/:id/integrations/datadog Parameters: -| Parameter | Type | Required | Description | -| ---------------------- | ------- | -------- | ----------- | -| `api_key` | string | true | API key used for authentication with Datadog | -| `api_url` | string | false | (Advanced) The full URL for your Datadog site | -| `datadog_env` | string | false | For self-managed deployments, set the env% tag for all the data sent to Datadog. | -| `datadog_service` | string | false | Tag all data from this GitLab instance in Datadog. Useful when managing several self-managed deployments | -| `datadog_site` | string | false | The Datadog site to send data to. To send data to the EU site, use `datadoghq.eu` | -| `datadog_tags` | string | false | Custom tags in Datadog. Specify one tag per line in the format: `key:value\nkey2:value2` ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79665) in GitLab 14.8.) | +| Parameter | Type | Required | Description | +|:-----------------:|:------:|----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `api_key` | string | true | API key used for authentication with Datadog. | +| `api_url` | string | false | (Advanced) The full URL for your Datadog site | +| `datadog_env` | string | false | For self-managed deployments, set the env% tag for all the data sent to Datadog. | +| `datadog_service` | string | false | Tag all data from this GitLab instance in Datadog. Useful when managing several self-managed deployments | +| `datadog_site` | string | false | The Datadog site to send data to. To send data to the EU site, use `datadoghq.eu` | +| `datadog_tags` | string | false | Custom tags in Datadog. Specify one tag per line in the format: `key:value\nkey2:value2` ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79665) in GitLab 14.8.) | + diff --git a/doc/api/oauth2.md b/doc/api/oauth2.md index 7b38ac39b96..67ffe514764 100644 --- a/doc/api/oauth2.md +++ b/doc/api/oauth2.md @@ -24,10 +24,6 @@ GitLab supports the following authorization flows: and is recommended for both client and server apps. - **Authorization code:** Secure and common flow. Recommended option for secure server-side apps. -- **Implicit grant:** Originally designed for user-agent only apps, such as - single page web apps running on GitLab Pages. - The [Internet Engineering Task Force (IETF)](https://tools.ietf.org/html/draft-ietf-oauth-security-topics-09#section-2.1.2) - recommends against Implicit grant flow. - **Resource owner password credentials:** To be used **only** for securely hosted, first-party services. GitLab recommends against use of this flow. @@ -64,7 +60,7 @@ As OAuth 2.0 bases its security entirely on the transport layer, you should not URIs. For more information, see the [OAuth 2.0 RFC](https://tools.ietf.org/html/rfc6749#section-3.1.2.1) and the [OAuth 2.0 Threat Model RFC](https://tools.ietf.org/html/rfc6819#section-4.4.2.1). These factors are particularly important when using the -[Implicit grant flow](#implicit-grant-flow), where actual credentials are included in the `redirect_uri`. +[Implicit grant flow](#implicit-grant-flow-deprecated), where actual credentials are included in the `redirect_uri`. In the following sections you can find detailed instructions on how to obtain authorization with each flow. @@ -242,40 +238,6 @@ authorization request. You can now make requests to the API with the access token returned. -### Implicit grant flow - -WARNING: -Implicit grant flow is inherently insecure and the IETF has removed it in [OAuth 2.1](https://oauth.net/2.1/). -It is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/288516) for use in GitLab 14.0, and is planned for -[removal](https://gitlab.com/gitlab-org/gitlab/-/issues/344609) in GitLab 15.0. - -We recommend that you use [Authorization code with PKCE](#authorization-code-with-proof-key-for-code-exchange-pkce) -instead. - -Unlike the authorization code flow, the client receives an `access token` -immediately as a result of the authorization request. The flow does not use the -client secret or the authorization code, as the application -code and storage is accessible on client browsers and mobile devices. - -To request the access token, you should redirect the user to the -`/oauth/authorize` endpoint using `token` response type: - -```plaintext -https://gitlab.example.com/oauth/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&response_type=token&state=YOUR_UNIQUE_STATE_HASH&scope=REQUESTED_SCOPES -``` - -This prompts the user to approve the applications access to their account -based on the scopes specified in `REQUESTED_SCOPES` and then redirect back to -the `REDIRECT_URI` you provided. The [scope parameter](../integration/oauth_provider.md#authorized-applications) - is a space-separated list of scopes you want to have access to (for example, `scope=read_user+profile` -would request `read_user` and `profile` scopes). The redirect -includes a fragment with `access_token` as well as token details in GET -parameters, for example: - -```plaintext -https://example.com/oauth/redirect#access_token=ABCDExyz123&state=YOUR_UNIQUE_STATE_HASH&token_type=bearer&expires_in=3600 -``` - ### Resource owner password credentials flow NOTE: @@ -357,6 +319,40 @@ access_token = client.password.get_token('user@example.com', 'secret') puts access_token.token ``` +### Implicit grant flow (DEPRECATED) + +WARNING: +Implicit grant flow is inherently insecure and the IETF has removed it in [OAuth 2.1](https://oauth.net/2.1/). +It is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/288516) for use in GitLab 14.0, and is planned for +[removal](https://gitlab.com/gitlab-org/gitlab/-/issues/344609) in GitLab 15.0. + +We recommend that you use [Authorization code with PKCE](#authorization-code-with-proof-key-for-code-exchange-pkce) +instead. + +Unlike the authorization code flow, the client receives an `access token` +immediately as a result of the authorization request. The flow does not use the +client secret or the authorization code, as the application +code and storage is accessible on client browsers and mobile devices. + +To request the access token, you should redirect the user to the +`/oauth/authorize` endpoint using `token` response type: + +```plaintext +https://gitlab.example.com/oauth/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&response_type=token&state=YOUR_UNIQUE_STATE_HASH&scope=REQUESTED_SCOPES +``` + +This prompts the user to approve the applications access to their account +based on the scopes specified in `REQUESTED_SCOPES` and then redirect back to +the `REDIRECT_URI` you provided. The [scope parameter](../integration/oauth_provider.md#authorized-applications) + is a space-separated list of scopes you want to have access to (for example, `scope=read_user+profile` +would request `read_user` and `profile` scopes). The redirect +includes a fragment with `access_token` as well as token details in GET +parameters, for example: + +```plaintext +https://example.com/oauth/redirect#access_token=ABCDExyz123&state=YOUR_UNIQUE_STATE_HASH&token_type=bearer&expires_in=3600 +``` + ## Access GitLab API with `access token` The `access token` allows you to make requests to the API on behalf of a user. diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md index 417ccba26a0..b6f7ea7aad4 100644 --- a/doc/development/api_graphql_styleguide.md +++ b/doc/development/api_graphql_styleguide.md @@ -827,35 +827,54 @@ A description of a field or argument is given using the `description:` keyword. For example: ```ruby -field :id, GraphQL::Types::ID, description: 'ID of the resource.' +field :id, GraphQL::Types::ID, description: 'ID of the issue.' +field :confidential, GraphQL::Types::Boolean, description: 'Indicates the issue is confidential.' +field :closed_at, Types::TimeType, description: 'Timestamp of when the issue was closed.' ``` -Descriptions of fields and arguments are viewable to users through: +You can view descriptions of fields and arguments in: - The [GraphiQL explorer](#graphiql). - The [static GraphQL API reference](../api/graphql/reference/index.md). ### Description style guide -To ensure consistency, the following should be followed whenever adding or updating -descriptions: +#### Language and punctuation -- Mention the name of the resource in the description. Example: - `'Labels of the issue'` (issue being the resource). -- Use `"{x} of the {y}"` where possible. Example: `'Title of the issue'`. - Do not start descriptions with `The` or `A`, for consistency and conciseness. -- Descriptions of `GraphQL::Types::Boolean` fields should answer the question: "What does - this field do?". Example: `'Indicates project has a Git repository'`. -- Always include the word `"timestamp"` when describing an argument or - field of type `Types::TimeType`. This lets the reader know that the - format of the property is `Time`, rather than just `Date`. -- Must end with a period (`.`). +Use `{x} of the {y}` where possible, where `{x}` is the item you're describing, +and `{y}` is the resource it applies to. For example: -Example: +```plaintext +ID of the issue. +``` + +Do not start descriptions with `The` or `A`, for consistency and conciseness. + +End all descriptions with a period (`.`). + +#### Booleans + +For a boolean field (`GraphQL::Types::Boolean`), start with a verb that describes +what it does. For example: + +```plaintext +Indicates the issue is confidential. +``` + +If necessary, provide the default. For example: + +```plaintext +Sets the issue to confidential. Default is false. +``` + +#### `Types::TimeType` field description + +For `Types::TimeType` GraphQL fields, include the word `timestamp`. This lets +the reader know that the format of the property is `Time`, rather than just `Date`. + +For example: ```ruby -field :id, GraphQL::Types::ID, description: 'ID of the issue.' -field :confidential, GraphQL::Types::Boolean, description: 'Indicates the issue is confidential.' field :closed_at, Types::TimeType, description: 'Timestamp of when the issue was closed.' ``` diff --git a/doc/development/documentation/restful_api_styleguide.md b/doc/development/documentation/restful_api_styleguide.md index 4d654b6b901..8a505ed84a8 100644 --- a/doc/development/documentation/restful_api_styleguide.md +++ b/doc/development/documentation/restful_api_styleguide.md @@ -83,23 +83,25 @@ to describe the GitLab release that introduced the API call. Use the following table headers to describe the methods. Attributes should always be in code blocks using backticks (`` ` ``). -Sort the attributes in the table: first, required, then alphabetically. +Sort the table by required attributes first, then alphabetically. ```markdown | Attribute | Type | Required | Description | |:-----------------------------|:--------------|:-----------------------|:-----------------------------------------------------| -| `user` | string | **{check-circle}** Yes | The GitLab username. | -| `assignee_ids` **(PREMIUM)** | integer array | **{dotted-circle}** No | The IDs of the users to assign the issue to. | -| `confidential` | boolean | **{dotted-circle}** No | Set an issue to be confidential. Default is `false`. | +| `title` | string | **{check-circle}** Yes | Title of the issue. | +| `assignee_ids` **(PREMIUM)** | integer array | **{dotted-circle}** No | IDs of the users to assign the issue to. | +| `confidential` | boolean | **{dotted-circle}** No | Sets the issue to confidential. Default is `false`. | ``` Rendered example: | Attribute | Type | Required | Description | |:-----------------------------|:--------------|:-----------------------|:-----------------------------------------------------| -| `user` | string | **{check-circle}** Yes | The GitLab username. | -| `assignee_ids` **(PREMIUM)** | integer array | **{dotted-circle}** No | The IDs of the users to assign the issue to. | -| `confidential` | boolean | **{dotted-circle}** No | Set an issue to be confidential. Default is `false`. | +| `title` | string | **{check-circle}** Yes | Title of the issue. | +| `assignee_ids` **(PREMIUM)** | integer array | **{dotted-circle}** No | IDs of the users to assign the issue to. | +| `confidential` | boolean | **{dotted-circle}** No | Sets the issue to confidential. Default is `false`. | + +For information about writing attribute descriptions, see the [GraphQL API description style guide](../api_graphql_styleguide.md#description-style-guide). ## cURL commands diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md index a670ba35ab0..0a0615c03e4 100644 --- a/doc/subscriptions/self_managed/index.md +++ b/doc/subscriptions/self_managed/index.md @@ -126,31 +126,6 @@ Cloud licensing manages licenses for self-managed GitLab subscription plans. Clo - Activation: Unlock plan features and activate your self-managed instance by using an activation code. - License sync: Sync subscription data between your self-managed instance and GitLab. -### What cloud licensing includes - -#### Auto-renewals - -For renewals that occur on or after 2021-08-01, your subscriptions will auto-renew. -You have the option to manually cancel in the Customers Portal any time until thirty (30) days before renewal. - -#### Cloud licensing - -You can activate and manage your GitLab licenses by using the Customers Portal. -This feature was formerly known as Seat Link. - -#### Operational data - -Service data helps GitLab improve the product experience and provide proactive support. -Most data is categorized as optional and can be disabled. Data that is categorized as -operational, like number of issues, pipelines, merge requests, and version, is not configurable. - -See our [service usage privacy page](https://about.gitlab.com/handbook/legal/privacy/services-usage-data/) -for details about what information is collected. - -#### Quarterly subscription reconciliation - -See the [quarterly subscription reconciliation section](../quarterly_reconciliation.md) for more information. - ### How cloud licensing works #### Add your license diff --git a/doc/user/group/settings/group_access_tokens.md b/doc/user/group/settings/group_access_tokens.md index 8ccbbd50495..84af6794970 100644 --- a/doc/user/group/settings/group_access_tokens.md +++ b/doc/user/group/settings/group_access_tokens.md @@ -16,9 +16,10 @@ You can use a group access token to authenticate: - With the [GitLab API](../../../api/index.md#personalprojectgroup-access-tokens). - In [GitLab 14.2](https://gitlab.com/gitlab-org/gitlab/-/issues/330718) and later, authenticate with Git over HTTPS. + Use: -After you configure a group access token, you don't need a password when you authenticate. -Instead, you can enter any non-blank value. + - Any non-blank value as a username. + - The group access token as the password. Group access tokens are similar to [project access tokens](../../project/settings/project_access_tokens.md) and [personal access tokens](../../profile/personal_access_tokens.md), except they are diff --git a/workhorse/internal/upload/destination/objectstore/s3_session.go b/workhorse/internal/upload/destination/objectstore/s3_session.go index a0c1f099145..aa38f18ed7a 100644 --- a/workhorse/internal/upload/destination/objectstore/s3_session.go +++ b/workhorse/internal/upload/destination/objectstore/s3_session.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/endpoints" "github.com/aws/aws-sdk-go/aws/session" "gitlab.com/gitlab-org/gitlab/workhorse/internal/config" @@ -70,7 +71,23 @@ func setupS3Session(s3Credentials config.S3Credentials, s3Config config.S3Config } if s3Config.Endpoint != "" { - cfg.Endpoint = aws.String(s3Config.Endpoint) + // The administrator has configured an S3 endpoint override, + // e.g. to make use of S3 IPv6 support or S3 FIPS mode. We + // need to configure a custom resolver to make sure that + // the custom endpoint is only used for S3 API calls, and not + // for STS API calls. + s3CustomResolver := func(service, region string, optFns ...func(*endpoints.Options)) (endpoints.ResolvedEndpoint, error) { + if service == endpoints.S3ServiceID { + return endpoints.ResolvedEndpoint{ + URL: s3Config.Endpoint, + SigningRegion: region, + }, nil + } + + return endpoints.DefaultResolver().EndpointFor(service, region, optFns...) + } + + cfg.EndpointResolver = endpoints.ResolverFunc(s3CustomResolver) } sess, err := session.NewSession(cfg) diff --git a/workhorse/internal/upload/destination/objectstore/s3_session_test.go b/workhorse/internal/upload/destination/objectstore/s3_session_test.go index 5d57b4f9af8..4bbe38f90ec 100644 --- a/workhorse/internal/upload/destination/objectstore/s3_session_test.go +++ b/workhorse/internal/upload/destination/objectstore/s3_session_test.go @@ -5,6 +5,7 @@ import ( "time" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/endpoints" "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitlab/workhorse/internal/config" @@ -17,7 +18,9 @@ func TestS3SessionSetup(t *testing.T) { sess, err := setupS3Session(credentials, cfg) require.NoError(t, err) - require.Equal(t, aws.StringValue(sess.Config.Region), "us-west-1") + s3Config := sess.ClientConfig(endpoints.S3ServiceID) + require.Equal(t, "https://s3.us-west-1.amazonaws.com", s3Config.Endpoint) + require.Equal(t, "us-west-1", s3Config.SigningRegion) require.True(t, aws.BoolValue(sess.Config.S3ForcePathStyle)) require.Equal(t, len(sessionCache.sessions), 1) @@ -29,6 +32,26 @@ func TestS3SessionSetup(t *testing.T) { ResetS3Session(cfg) } +func TestS3SessionEndpointSetup(t *testing.T) { + credentials := config.S3Credentials{} + const customS3Endpoint = "https://example.com" + const region = "us-west-2" + cfg := config.S3Config{Region: region, PathStyle: true, Endpoint: customS3Endpoint} + + sess, err := setupS3Session(credentials, cfg) + require.NoError(t, err) + + // ClientConfig is what is ultimately used by an S3 client + s3Config := sess.ClientConfig(endpoints.S3ServiceID) + require.Equal(t, customS3Endpoint, s3Config.Endpoint) + require.Equal(t, region, s3Config.SigningRegion) + + stsConfig := sess.ClientConfig(endpoints.StsServiceID) + require.Equal(t, "https://sts.amazonaws.com", stsConfig.Endpoint, "STS should use default endpoint") + + ResetS3Session(cfg) +} + func TestS3SessionExpiry(t *testing.T) { credentials := config.S3Credentials{} cfg := config.S3Config{Region: "us-west-1", PathStyle: true}