Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uptake of SecretText #471

Merged
merged 67 commits into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from 48 commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
3e97cb9
AzureFunctionsOAuth2 and used OAuth2 functions
darjoo Jan 8, 2024
553868f
Oauth2 secrettext uptake
darjoo Jan 8, 2024
965c098
CustExpSurveyReqImpl accesstoken as secrettext
darjoo Jan 8, 2024
3ff1796
SharepointAuthorization secrettext uptake
darjoo Jan 8, 2024
ab44ec4
OAuth uptake
darjoo Jan 8, 2024
c2d12da
Update sharepoint authorization test
darjoo Jan 8, 2024
9148b10
Update AzureFunctionsOAuth2
darjoo Jan 8, 2024
ef83a4c
StorageServiceAuthorization uptake
darjoo Jan 8, 2024
69d2bea
Update SharePointAuthorizationCode
darjoo Jan 8, 2024
90c7b03
Update SharepointAuthorization
darjoo Jan 8, 2024
994dec0
Update SharepointAuth
darjoo Jan 8, 2024
71ba7b7
Update AuthFormatHelper
darjoo Jan 8, 2024
53deca3
Add pragma for the obsoleted usages
darjoo Jan 8, 2024
c2f52b9
Merge branch 'main' of https://github.com/microsoft/BCApps into priva…
darjoo Jan 8, 2024
8996727
Pragma and secret for RestClient and more OAuth2
darjoo Jan 8, 2024
4cee385
More uptake
darjoo Jan 10, 2024
dcad3cc
Cryptography management
darjoo Jan 10, 2024
8b9422b
Entitytext
darjoo Jan 10, 2024
35b91c0
Crypto
darjoo Jan 12, 2024
c00c6b1
More Cryptography management changes
darjoo Jan 17, 2024
13f5f64
Merge branch 'main' of https://github.com/microsoft/BCApps into priva…
darjoo Jan 18, 2024
e82713c
Merge branch 'main' of https://github.com/microsoft/BCApps into priva…
darjoo Jan 22, 2024
eba20bb
Update
darjoo Jan 22, 2024
5e0af55
Update Cryptographymanagement
darjoo Jan 22, 2024
ea4a1fe
Add preprocesstags in SharePointAuthorizationCode
darjoo Jan 22, 2024
d751b6f
Update Password
darjoo Jan 22, 2024
391148f
Update Entity Text
darjoo Jan 22, 2024
7496009
Revert InitializeRSA from CertificateRequest
darjoo Jan 22, 2024
61afb39
Update tests
darjoo Jan 22, 2024
89a7ca6
Update AI module
darjoo Jan 22, 2024
41c6b58
Add AcquireTokensWithCertificate with cert password
darjoo Jan 22, 2024
c96d926
Update with obsoletions
darjoo Jan 23, 2024
580b1c5
Update with pragmas for tests
darjoo Jan 23, 2024
a17692c
Missing facade obsoletions
darjoo Jan 23, 2024
092ccf4
DESCryptoserviceProvider obsoletions
darjoo Jan 23, 2024
f1eaafd
RijndaelCryptography obsoletions
darjoo Jan 23, 2024
36b335c
DSACryptoServiceProvider obsoletions
darjoo Jan 23, 2024
de757f5
RSACryptoServiceProvider obsoletions
darjoo Jan 23, 2024
ac1979d
SignatureKey obsoletions
darjoo Jan 23, 2024
c9a544f
X509Certificate2 obsoletions
darjoo Jan 23, 2024
c3d013e
Obsolete more functions
darjoo Jan 24, 2024
0af9655
Merge branch 'main' of https://github.com/microsoft/BCApps into priva…
darjoo Jan 24, 2024
fad2833
Fix tests and revert some changes
darjoo Jan 25, 2024
458d705
Merge branch 'main' of https://github.com/microsoft/BCApps into priva…
darjoo Jan 25, 2024
7fa5bcd
Revert event
darjoo Jan 26, 2024
713067c
Update OAuth2
darjoo Jan 29, 2024
d11cb3a
Merge branch 'main' of https://github.com/microsoft/BCApps into priva…
darjoo Jan 29, 2024
b0c6387
Update tests and change Sys App to be debuggable
darjoo Jan 29, 2024
24a4cca
Missing CertificatePassword use
darjoo Jan 30, 2024
20725ff
Refactor to remove duplicate code in OAuth2Impl
darjoo Jan 30, 2024
6f5783c
Merge branch 'main' of https://github.com/microsoft/BCApps into priva…
darjoo Jan 30, 2024
d438c41
Remove some [NonDebuggable]
darjoo Jan 30, 2024
265bfb1
Merge branch 'main' of https://github.com/microsoft/BCApps into priva…
darjoo Feb 5, 2024
8222105
Remove nondebuggable and additional fixes
darjoo Feb 6, 2024
40cd2ad
Missing clean tag
darjoo Feb 6, 2024
4d6be98
Merge branch 'main' of https://github.com/microsoft/BCApps into priva…
darjoo Feb 6, 2024
dfd0d89
Remove clean24 tags for OAuth2 due to baseapp
darjoo Feb 6, 2024
18f6a47
Merge branch 'main' of https://github.com/microsoft/BCApps into priva…
darjoo Feb 8, 2024
e95fab8
Unwrap changepassword
darjoo Feb 8, 2024
681f7a2
Missing pragma
darjoo Feb 8, 2024
f230451
Merge branch 'main' of https://github.com/microsoft/BCApps into priva…
darjoo Feb 8, 2024
f84f34d
Casing
darjoo Feb 8, 2024
3015696
Intenral test event
darjoo Feb 8, 2024
285045e
#endif preprocessor wasn't removed
darjoo Feb 8, 2024
70a5b33
Revert removal
darjoo Feb 9, 2024
1af910e
Update Sharepoint Authorization test
darjoo Feb 9, 2024
a10cc33
Change app.json for test to OnPrem
darjoo Feb 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ codeunit 7772 "Azure OpenAI Impl"
var
AzureKeyVault: Codeunit "Azure Key Vault";
EnvironmentInformation: Codeunit "Environment Information";
KVSecret: Text;
KVSecret: SecretText;
begin
if not EnvironmentInformation.IsSaaSInfrastructure() then
exit;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ codeunit 7800 "Azure Functions Authentication"
InherentEntitlements = X;
InherentPermissions = X;

#if not CLEAN24
/// <summary>
/// Creates OAuth2 authentication instance of Azure function interface.
/// </summary>
Expand All @@ -26,13 +27,35 @@ codeunit 7800 "Azure Functions Authentication"
/// <param name="ResourceURL">The Application ID URI</param>
/// <returns>Instance of Azure function response object.</returns>
[NonDebuggable]
[Obsolete('Use CreateOAuth2 with SecretText data type for ClientSecret.', '24.0')]
procedure CreateOAuth2(Endpoint: Text; AuthenticationCode: Text; ClientId: Text; ClientSecret: Text; OAuthAuthorityUrl: Text; RedirectURL: Text; ResourceURL: Text): Interface "Azure Functions Authentication"
var
AzureFunctionsOAuth2: Codeunit "Azure Functions OAuth2";
begin
AzureFunctionsOAuth2.SetAuthParameters(Endpoint, AuthenticationCode, ClientId, ClientSecret, OAuthAuthorityUrl, RedirectURL, ResourceURL);
exit(AzureFunctionsOAuth2);
end;
#endif

/// <summary>
/// Creates OAuth2 authentication instance of Azure function interface.
/// </summary>
/// <param name="Endpoint">Azure function endpoint</param>
/// <param name="AuthenticationCode">Azure function authentication code, empty if anonymous.</param>
/// <param name="ClientId">The Application (client) ID that the Azure portal – App registrations experience assigned to your app.</param>
/// <param name="ClientSecret">The Application (client) secret configured in the Azure Portal.</param>
/// <param name="OAuthAuthorityUrl">The identity authorization provider URL.</param>
/// <param name="RedirectURL">The redirectURL of your app, for azure function this could be empty</param>
/// <param name="ResourceURL">The Application ID URI</param>
/// <returns>Instance of Azure function response object.</returns>
[NonDebuggable]
procedure CreateOAuth2(Endpoint: Text; AuthenticationCode: Text; ClientId: Text; ClientSecret: SecretText; OAuthAuthorityUrl: Text; RedirectURL: Text; ResourceURL: Text): Interface "Azure Functions Authentication"
var
AzureFunctionsOAuth2: Codeunit "Azure Functions OAuth2";
begin
AzureFunctionsOAuth2.SetAuthParameters(Endpoint, AuthenticationCode, ClientId, ClientSecret, OAuthAuthorityUrl, RedirectURL, ResourceURL);
exit(AzureFunctionsOAuth2);
end;

/// <summary>
/// Creates code authentication instance of Azure function interface.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ codeunit 7802 "Azure Functions OAuth2" implements "Azure Functions Authenticatio
[NonDebuggable]
AuthenticationCodeGlobal, EndpointGlobal : Text;
[NonDebuggable]
ClientIdGlobal, ClientSecretGlobal, OAuthAuthorityUrlGlobal, RedirectURLGlobal, ResourceURLGlobal, AccessToken : Text;
ClientIdGlobal, OAuthAuthorityUrlGlobal, RedirectURLGlobal, ResourceURLGlobal : Text;
ClientSecretGlobal: SecretText;
AccessToken: SecretText;
BearerLbl: Label 'Bearer %1', Comment = '%1 is the access token', Locked = true;
FailedToGetTokenErr: Label 'Authorization failed to Azure function: %1', Locked = true;
AzureFunctionCategoryLbl: Label 'Connect to Azure Functions', Locked = true;

Expand All @@ -37,7 +40,7 @@ codeunit 7802 "Azure Functions OAuth2" implements "Azure Functions Authenticatio

OAuth2.AcquireTokenWithClientCredentials(ClientIdGlobal, ClientSecretGlobal, OAuthAuthorityUrlGlobal, RedirectURLGlobal, ResourceURLGlobal, AccessToken);

if AccessToken = '' then begin
if AccessToken.IsEmpty() then begin
UriBuilder.GetUri(Uri);
Dimensions.Add('FunctionHost', Format(Uri.GetHost()));
FeatureTelemetry.LogError('0000I75', AzureFunctionCategoryLbl, 'Acquiring token', StrSubstNo(FailedToGetTokenErr, Uri.GetHost()), '', Dimensions);
Expand All @@ -46,7 +49,7 @@ codeunit 7802 "Azure Functions OAuth2" implements "Azure Functions Authenticatio

RequestMessage.GetHeaders(Headers);
Headers.Remove('Authorization');
Headers.Add('Authorization', 'Bearer ' + AccessToken);
Headers.Add('Authorization', SecretStrSubstNo(BearerLbl, AccessToken));


if AuthenticationCodeGlobal <> '' then
Expand All @@ -58,7 +61,7 @@ codeunit 7802 "Azure Functions OAuth2" implements "Azure Functions Authenticatio
end;

[NonDebuggable]
procedure SetAuthParameters(Endpoint: Text; AuthenticationCode: Text; ClientId: Text; ClientSecret: Text; OAuthAuthorityUrl: Text; RedirectURL: Text; ResourceURL: Text)
procedure SetAuthParameters(Endpoint: Text; AuthenticationCode: Text; ClientId: Text; ClientSecret: SecretText; OAuthAuthorityUrl: Text; RedirectURL: Text; ResourceURL: Text)
begin
EndpointGlobal := Endpoint;
AuthenticationCodeGlobal := AuthenticationCode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ codeunit 2202 "Azure Key Vault Impl."
X509Certificate2: Codeunit X509Certificate2;
EnvironmentInformation: Codeunit "Environment Information";
CertificateThumbprint: Text;
EmptySecretText: SecretText;
begin
if CachedCertificatesDictionary.ContainsKey(CertificateName) then begin
Certificate := CachedCertificatesDictionary.Get(CertificateName);
Expand All @@ -136,7 +137,7 @@ codeunit 2202 "Azure Key Vault Impl."
end;
Certificate := NavAzureKeyVaultClient.GetAzureKeyVaultCertificate(CertificateName);
if EnvironmentInformation.IsSaaS() then begin
X509Certificate2.GetCertificateThumbprint(Certificate, '', CertificateThumbprint);
X509Certificate2.GetCertificateThumbprint(Certificate, EmptySecretText, CertificateThumbprint);
if CertificateThumbprint <> '' then
Session.LogMessage('0000C17', StrSubstNo(CertificateInfoTxt, CertificateName, CertificateThumbprint), Verbosity::Normal, DataClassification::SystemMetadata, TelemetryScope::ExtensionPublisher, 'Category', AzureKeyVaultTxt);
end;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ codeunit 9060 "Auth. Format Helper"
end;

[NonDebuggable]
procedure GetAccessKeyHashCode(StringToSign: Text; AccessKey: Text): Text;
procedure GetAccessKeyHashCode(StringToSign: Text; AccessKey: SecretText): Text;
var
CryptographyManagement: Codeunit "Cryptography Management";
HashAlgorithmType: Option HMACMD5,HMACSHA1,HMACSHA256,HMACSHA384,HMACSHA512;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ codeunit 9061 "Stor. Serv. Auth. SAS" implements "Storage Service Authorization"
end;

[NonDebuggable]
procedure SetSigningKey(NewSigningKey: Text)
procedure SetSigningKey(NewSigningKey: SecretText)
begin
SigningKey := NewSigningKey;
end;
Expand Down Expand Up @@ -241,8 +241,7 @@ codeunit 9061 "Stor. Serv. Auth. SAS" implements "Storage Service Authorization"
AuthFormatHelper: Codeunit "Auth. Format Helper";
[NonDebuggable]
StorageAccountName: Text;
[NonDebuggable]
SigningKey: Text;
SigningKey: SecretText;
SignedEncryptionScope: Text;
StartDate: DateTime;
EndDate: DateTime;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ codeunit 9064 "Stor. Serv. Auth. Shared Key" implements "Storage Service Authori
end;

[NonDebuggable]
procedure SetSharedKey(SharedKey: Text)
procedure SetSharedKey(SharedKey: SecretText)
begin
Secret := SharedKey;
end;
Expand All @@ -47,7 +47,7 @@ codeunit 9064 "Stor. Serv. Auth. Shared Key" implements "Storage Service Authori
SignaturePlaceHolderLbl: Label 'SharedKey %1:%2', Comment = '%1 = Account Name; %2 = Calculated Signature', Locked = true;
SecretCanNotBeEmptyErr: Label 'Secret (Access Key) must be provided';
begin
if Secret = '' then
if Secret.IsEmpty() then
Error(SecretCanNotBeEmptyErr);

StringToSign := CreateSharedKeyStringToSign(HttpRequestMessage, StorageAccount);
Expand Down Expand Up @@ -209,6 +209,5 @@ codeunit 9064 "Stor. Serv. Auth. Shared Key" implements "Storage Service Authori
var
AuthFormatHelper: Codeunit "Auth. Format Helper";
ApiVersion: Enum "Storage Service API Version";
[NonDebuggable]
Secret: Text;
Secret: SecretText;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ codeunit 9063 "Stor. Serv. Auth. Impl."
InherentPermissions = X;

[NonDebuggable]
procedure CreateSAS(SigningKey: Text; SignedVersion: Enum "Storage Service API Version"; SignedServices: List of [Enum "SAS Service Type"]; SignedResources: List of [Enum "SAS Resource Type"]; SignedPermissions: List of [Enum "SAS Permission"]; SignedExpiry: DateTime): Interface "Storage Service Authorization"
procedure CreateSAS(SigningKey: SecretText; SignedVersion: Enum "Storage Service API Version"; SignedServices: List of [Enum "SAS Service Type"]; SignedResources: List of [Enum "SAS Resource Type"]; SignedPermissions: List of [Enum "SAS Permission"]; SignedExpiry: DateTime): Interface "Storage Service Authorization"
var
OptionalParams: Record "SAS Parameters";
begin
Expand All @@ -21,7 +21,7 @@ codeunit 9063 "Stor. Serv. Auth. Impl."
end;

[NonDebuggable]
procedure CreateSAS(SigningKey: Text; SignedVersion: Enum "Storage Service API Version"; SignedServices: List of [Enum "SAS Service Type"]; SignedResources: List of [Enum "SAS Resource Type"]; SignedPermissions: List of [Enum "SAS Permission"]; SignedExpiry: DateTime; OptionalParams: Record "SAS Parameters"): Interface "Storage Service Authorization"
procedure CreateSAS(SigningKey: SecretText; SignedVersion: Enum "Storage Service API Version"; SignedServices: List of [Enum "SAS Service Type"]; SignedResources: List of [Enum "SAS Resource Type"]; SignedPermissions: List of [Enum "SAS Permission"]; SignedExpiry: DateTime; OptionalParams: Record "SAS Parameters"): Interface "Storage Service Authorization"
var
StorServAuthSAS: Codeunit "Stor. Serv. Auth. SAS";
begin
Expand All @@ -42,7 +42,7 @@ codeunit 9063 "Stor. Serv. Auth. Impl."
end;

[NonDebuggable]
procedure SharedKey(SharedKeyToUse: Text; ApiVersion: Enum "Storage Service API Version"): Interface "Storage Service Authorization"
procedure SharedKey(SharedKeyToUse: SecretText; ApiVersion: Enum "Storage Service API Version"): Interface "Storage Service Authorization"
var
StorServAuthSharedKey: Codeunit "Stor. Serv. Auth. Shared Key";
begin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,15 @@ codeunit 9062 "Storage Service Authorization"
exit(StorServAuthImpl.CreateSAS(SigningKey, SignedVersion, SignedServices, SignedResources, SignedPermissions, SignedExpiry, OptionalSASParameters));
end;

#if not CLEAN24
/// <summary>
/// Creates a Shared Key authorization mechanism for HTTP requests to Azure Storage Services.
/// See: https://go.microsoft.com/fwlink/?linkid=2210396
/// </summary>
/// <param name="SharedKey">The shared key to use.</param>
/// <returns>A Shared Key authorization.</returns>
[NonDebuggable]
[Obsolete('Use CreateSharedKey with SecretText data type for SharedKey.', '24.0')]
procedure CreateSharedKey(SharedKey: Text): Interface "Storage Service Authorization"
var
StorServAuthImpl: Codeunit "Stor. Serv. Auth. Impl.";
Expand All @@ -77,12 +79,43 @@ codeunit 9062 "Storage Service Authorization"
/// <param name="ApiVersion">The API version to use.</param>
/// <returns>A Shared Key authorization.</returns>
[NonDebuggable]
[Obsolete('Use CreateSharedKey with SecretText data type for SharedKey.', '24.0')]
procedure CreateSharedKey(SharedKey: Text; ApiVersion: Enum "Storage Service API Version"): Interface "Storage Service Authorization"
var
StorServAuthImpl: Codeunit "Stor. Serv. Auth. Impl.";
begin
exit(StorServAuthImpl.SharedKey(SharedKey, ApiVersion));
end;
#endif

/// <summary>
/// Creates a Shared Key authorization mechanism for HTTP requests to Azure Storage Services.
/// See: https://go.microsoft.com/fwlink/?linkid=2210396
/// </summary>
/// <param name="SharedKey">The shared key to use.</param>
/// <returns>A Shared Key authorization.</returns>
[NonDebuggable]
procedure CreateSharedKey(SharedKey: SecretText): Interface "Storage Service Authorization"
var
StorServAuthImpl: Codeunit "Stor. Serv. Auth. Impl.";
begin
exit(StorServAuthImpl.SharedKey(SharedKey, GetDefaultAPIVersion()));
end;

/// <summary>
/// Creates a Shared Key authorization mechanism for HTTP requests to Azure Storage Services.
/// See: https://go.microsoft.com/fwlink/?linkid=2210396
/// </summary>
/// <param name="SharedKey">The shared key to use.</param>
/// <param name="ApiVersion">The API version to use.</param>
/// <returns>A Shared Key authorization.</returns>
[NonDebuggable]
procedure CreateSharedKey(SharedKey: SecretText; ApiVersion: Enum "Storage Service API Version"): Interface "Storage Service Authorization"
var
StorServAuthImpl: Codeunit "Stor. Serv. Auth. Impl.";
begin
exit(StorServAuthImpl.SharedKey(SharedKey, ApiVersion));
end;

/// <summary>
/// Uses a pre-generated account SAS (Shared Access Signature) for authorizing HTTP request to Azure Storage Services.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,23 @@ codeunit 1463 CertificateRequest
/// <param name="KeySize">The size of the key in bits.</param>
/// <param name="IncludePrivateParameters">True to include a public and private RSA key in KeyAsXmlString. False to include only the public key.</param>
/// <param name="KeyAsXmlString">Returns an XML string that contains the key of the RSA object that was created.</param>
[NonDebuggable]
procedure InitializeRSA(KeySize: Integer; IncludePrivateParameters: Boolean; var KeyAsXmlString: Text)
begin
CertSigningRequestImpl.InitializeRSA(KeySize, IncludePrivateParameters, KeyAsXmlString);
end;

/// <summary>
/// Initializes a new instance of RSACryptoServiceProvider with the specified key size and returns the key as an XML string.
/// </summary>
/// <param name="KeySize">The size of the key in bits.</param>
/// <param name="IncludePrivateParameters">True to include a public and private RSA key in KeyAsXmlString. False to include only the public key.</param>
/// <param name="KeyAsXmlString">Returns an XML string that contains the key of the RSA object that was created.</param>
procedure InitializeRSA(KeySize: Integer; IncludePrivateParameters: Boolean; var KeyAsXmlString: SecretText)
begin
CertSigningRequestImpl.InitializeRSA(KeySize, IncludePrivateParameters, KeyAsXmlString);
end;

/// <summary>
/// Initializes a new instance of the CertificateRequest with the specified parameters and the initialized RSA key.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,23 @@ codeunit 1464 "CertificateRequest Impl."
EndCertReqTok: Label '-----END CERTIFICATE REQUEST-----', Locked = true;
DepricatedHashAlgorithmsMsg: Label 'In compliance with the Microsoft Secure Hash Algorithm deprecation policy SHA1 and MD5 hash alghoritms have been deprecated.';

[NonDebuggable]
procedure InitializeRSA(KeySize: Integer; IncludePrivateParameters: Boolean; var KeyAsXmlString: Text)
begin
DotNetRSACryptoServiceProvider := DotNetRSACryptoServiceProvider.RSACryptoServiceProvider(KeySize);
DotNetRSACryptoServiceProvider.PersistKeyInCsp(false);
KeyAsXmlString := DotNetRSACryptoServiceProvider.ToXmlString(IncludePrivateParameters);
end;

procedure InitializeRSA(KeySize: Integer; IncludePrivateParameters: Boolean; var KeyAsXmlString: SecretText)
var
[NonDebuggable]
KeyAsXml: Text;
begin
InitializeRSA(KeySize, IncludePrivateParameters, KeyAsXml);
KeyAsXmlString := KeyAsXml;
end;

procedure InitializeCertificateRequestUsingRSA(SubjectName: Text; HashAlgorithm: Enum "Hash Algorithm"; RSASignaturePaddingMode: Enum "RSA Signature Padding")
var
DotNetHashAlgorithmName: DotNet HashAlgorithmName;
Expand Down
Loading
Loading