2023 Wave 2 – v23: New SecretText data type to protect credentials and sensitive textual values

2023 Wave 2 – v23: New SecretText data type to protect credentials and sensitive textual values (English Version)

2023 Wave 2 – v23: Nuevo tipo de datos SecretText para proteger credenciales y valores textuales sensibles.

En el código AL, una credencial queda expuesta en una sesión de depuración o en una instantánea durante toda su vida útil si no está protegida por el atributo NonDebuggable en el ámbito de un procedimiento o en la variable en la que se aloja. A un valor SecretText se le puede asignar cualquier valor de tipo Texto o Código. El tiempo de vida de los tokens está protegido del depurador si se recuperan y son transformados a un valor SecretText.

Aquí el ejemplo del comportamiento de este nuevo tipo de datos.

procedure Assignments()
var
    PlainText: Text;
    Credential: SecretText;
begin
    Credential := PlainText; // Allowed
    PlainText := Credential; // Blocked

    ConsumePlainText(PlainText); // Allowed
    ConsumePlainText(Credential); // Blocked

    Credential := ProduceCredential(); //Allowed
    PlainText := ProduceCredential(); // Blocked
end;

procedure ConsumePlainText(PlainText: Text)
begin
end;

procedure ProduceCredential(): SecretText
begin
end;

El tipo de datos SecretText ofrece las siguientes funciones:

procedure SecretStrSubstNoExamples()
var
    First: SecretText;
    Second: SecretText;
    Result: SecretText;
begin
    // Concatenation
    Result := SecretStrSubstNo('%1%2', First, Second);

    // Build a header value
    Result := SecretStrSubstNo('Bearer %1', First);

    // Build a comma separated value list
    Result := SecretStrSubstNo('%1,%2', First, Second);
end;

Las siguientes funciones del tipo de datos HttpClient se han sobrecargado y permiten ahora el uso de variables del tipo SecretText:

Las siguientes funciones del tipo de datos HttpContent se han sobrecargado y permiten ahora el uso de variables del tipo SecretText, también hay funciones nuevas:

Las siguientes funciones del tipo de datos HttpHeaders se han sobrecargado y permiten ahora el uso de variables del tipo SecretText, también hay funciones nuevas:

Las siguientes funciones del tipo de datos HttpRequestMessage son nuevas y permiten ahora el uso de variables del tipo SecretText:

El valor de retorno y el parámetro del siguiente ejemplo no serán depurables:

// The return value and parameter will not be debuggable
    procedure Send(ContentTxt: SecretText; Credential: SecretText; TargetUri: SecretText)
    var
        Request: HttpRequestMessage;
        Response: HttpResponseMessage;
        Client: HttpClient;
        Headers: HttpHeaders;
        Content: HttpContent;
    begin
        Request.SetSecretRequestUri(TargetUri);
        Content.WriteFrom(ContentTxt);
        Request.GetHeaders(Headers);
        Headers.Add('Authorization', SecretText.SecretStrSubstNo('Bearer %1', Credential));
        Request.Content := Content;
        Client.Send(Request, Response);
    end;

Otro ejemplo del uso de este nuevo tipo de datos:

procedure SendAuthenticatedRequestToApi(UriTemplate: Text; BearerToken: SecretText; KeyParameter: SecretText; SecretBody: SecretText)
    var
        Client: HttpClient;
        Headers: HttpHeaders;
        SecretHeader: SecretText;
        SecretUri: SecretText;

        RequestMessage: HttpRequestMessage;
    begin
        SecretHeader := SecretStrSubstNo('Bearer %1', BearerToken);

        RequestMessage.GetHeaders(Headers);

        // The header is added and remains hidden when debugging the headers
        // of the request message
        Headers.Add('Authorization', SecretHeader);

        // Headers.Contains('Authorization') - false
        // Headers.ContainsSecret('Authorization') - true
        // Headers.GetSecretValues must be used to get the values.
        // It is not possible to retrieve the header value as a plain text.

        SecretUri := SecretStrSubstNo(UriTemplate, KeyParameter);
        RequestMessage.SetSecretRequestUri(SecretUri);

        // RequestMessage.GetSecretRequestUri can be used to retrieve the request uri.
        // It cannot be retrieved by GetRequestUri as a plain text.

        RequestMessage.Content.WriteFrom(SecretBody);

        // RequestMessage.Content.ReadAs can only read back the body in a SecretText destination

        SendMessageAndHandleResponse(Client, RequestMessage);
    end;

    [NonDebuggable]
    procedure SendMessageAndHandleResponse(Client: HttpClient; Request: HttpRequestMessage) CredentialFromResponse: SecretText
    var
        Response: HttpResponseMessage;
    begin
        Client.Send(Request, Response);
        Response.Content.ReadAs(CredentialFromResponse);
    end;

Espero que haya sido de utilidad esta información.


2023 Wave 2 – v23: New SecretText data type to protect credentials and sensitive textual values

In AL code, a credential is exposed in a debug session or snapshot for its entire lifetime if it is not protected by the NonDebuggable attribute in the scope of a procedure or in the variable in which it is hosted. A SecretText value can be assigned any value of type Text or Code. The lifetime of tokens is protected from the debugger if they are retrieved and transformed to a SecretText value.

Here is an example of the behavior of this new data type.

procedure Assignments()
var
    PlainText: Text;
    Credential: SecretText;
begin
    Credential := PlainText; // Allowed
    PlainText := Credential; // Blocked

    ConsumePlainText(PlainText); // Allowed
    ConsumePlainText(Credential); // Blocked

    Credential := ProduceCredential(); //Allowed
    PlainText := ProduceCredential(); // Blocked
end;

procedure ConsumePlainText(PlainText: Text)
begin
end;

procedure ProduceCredential(): SecretText
begin
end;

The SecretText data type offers the following methods:

procedure SecretStrSubstNoExamples()
var
    First: SecretText;
    Second: SecretText;
    Result: SecretText;
begin
    // Concatenation
    Result := SecretStrSubstNo('%1%2', First, Second);

    // Build a header value
    Result := SecretStrSubstNo('Bearer %1', First);

    // Build a comma separated value list
    Result := SecretStrSubstNo('%1,%2', First, Second);
end;

The following methods of the HttpClient data type have been overloaded and now allow the use of variables of type SecretText:

The following methods of the HttpContent data type have been overloaded and now allow the use of variables of the SecretText type, and there are also new methods:

The following methods of the HttpHeaders data type have been overloaded and now allow the use of variables of the SecretText type, and there are also new methods:

The following methods of the HttpRequestMessage data type are new and now allow the use of variables of type SecretText:

The return value and parameter of the following example will not be debuggable:

// The return value and parameter will not be debuggable
    procedure Send(ContentTxt: SecretText; Credential: SecretText; TargetUri: SecretText)
    var
        Request: HttpRequestMessage;
        Response: HttpResponseMessage;
        Client: HttpClient;
        Headers: HttpHeaders;
        Content: HttpContent;
    begin
        Request.SetSecretRequestUri(TargetUri);
        Content.WriteFrom(ContentTxt);
        Request.GetHeaders(Headers);
        Headers.Add('Authorization', SecretText.SecretStrSubstNo('Bearer %1', Credential));
        Request.Content := Content;
        Client.Send(Request, Response);
    end;

Another example of the use of this new type of data:

procedure SendAuthenticatedRequestToApi(UriTemplate: Text; BearerToken: SecretText; KeyParameter: SecretText; SecretBody: SecretText)
    var
        Client: HttpClient;
        Headers: HttpHeaders;
        SecretHeader: SecretText;
        SecretUri: SecretText;

        RequestMessage: HttpRequestMessage;
    begin
        SecretHeader := SecretStrSubstNo('Bearer %1', BearerToken);

        RequestMessage.GetHeaders(Headers);

        // The header is added and remains hidden when debugging the headers
        // of the request message
        Headers.Add('Authorization', SecretHeader);

        // Headers.Contains('Authorization') - false
        // Headers.ContainsSecret('Authorization') - true
        // Headers.GetSecretValues must be used to get the values.
        // It is not possible to retrieve the header value as a plain text.

        SecretUri := SecretStrSubstNo(UriTemplate, KeyParameter);
        RequestMessage.SetSecretRequestUri(SecretUri);

        // RequestMessage.GetSecretRequestUri can be used to retrieve the request uri.
        // It cannot be retrieved by GetRequestUri as a plain text.

        RequestMessage.Content.WriteFrom(SecretBody);

        // RequestMessage.Content.ReadAs can only read back the body in a SecretText destination

        SendMessageAndHandleResponse(Client, RequestMessage);
    end;

    [NonDebuggable]
    procedure SendMessageAndHandleResponse(Client: HttpClient; Request: HttpRequestMessage) CredentialFromResponse: SecretText
    var
        Response: HttpResponseMessage;
    begin
        Client.Send(Request, Response);
        Response.Content.ReadAs(CredentialFromResponse);
    end;

I hope this information has been useful.


Más información / More information

Deja un comentario