Powershell - Unable to create repository using application identity

Resolved

Powershell - Unable to create repository using application identity

avatar

Hello there,

I am currently trying to migrate an existing script that performs batch operations from using a username and password to using an application identity. The script should create a repository using a given name, using an existing repository as template.

Logging in has worked so far:

    $appId = $ScriptConfig.ApplicationId
    $appSecret = $ScriptConfig.ApplicationSecret
    if ([string]::IsNullOrWhiteSpace($appId) -or [string]::IsNullOrWhiteSpace($appSecret)) {
        throw "ApplicationId and ApplicationSecret must be configured."
    }

    if ($OverrideOptionFilePath) {
        $optionDir = Split-Path $OverrideOptionFilePath -Parent
        if ($optionDir -and -not (Test-Path $optionDir)) {
            New-Item -ItemType Directory -Path $optionDir -Force | Out-Null
        }
        $override = Get-RDMPowerShellOverride
        $override.OptionFilePath = $OverrideOptionFilePath
        Set-RDMPowerShellOverride
    }

    Write-LogSimple -Message "Connecting to $DvlsUrl with application id '$appId'..." -Type "INFO"

    $ds = New-RDMDataSource -DVLS -Name $ScriptConfig.DataSourceName -Server $DvlsUrl -ScriptingTenantID $appId -ScriptingApplicationPassword $appSecret -SetDatasource -WarningAction SilentlyContinue
    Set-RDMDataSource $ds
    Set-RDMCurrentDataSource $ds


Unfortunately, trying to create a repository using the same login, yields in "Session does not seem authenticated" errors.

New-DSVault -Name $NewRepositoryName -ErrorAction Stop -SecurityLevel "Standard" -IsAllowedOffline $true -AllowedRolesList ("ROLE_01", "ROLE_02")


I read in the documentation that application identities have no permissions by default, but I am unsure how I would give it permission to create the vault. Here are my system permissions:


What permissions do I need to set / grant for this to work?

771d9cb7-c49e-41ec-80c0-6ef1078148a7.png

All Comments (7)

avatar

Hello,

Thank you for your feedback.

It's not a permission problem but rather a problem with the cmdlet you're using.

Since you created a data source using the RDM cmdlets, you should continue using the RDM cmdlets. The cmdlet to create is New-RDMVault which is an alias of the New-RDMRepository cmdlet.

Let us know if that helps.

Best regards,

Érica Poirier

avatar

Hello,

Thank you for the quick response! Running New-RDMVault seems to do something, but the script does not seem to actually create a repository? It claims that the creation and import of the data (which shows a progressbar too and takes a minute) is successful, but I am unable to find the created repository in the admin view.

function New-RepositoryFromTemplate {
    param (
        [string]$NewRepositoryName,
        [string]$TemplateRepositoryName,
        [string]$TemplateExportFile 
    )
    try {
        $templateRepo = Get-RDMRepository -ErrorAction SilentlyContinue | Where-Object { $_.Name -eq $TemplateRepositoryName } | Select-Object -First 1
        if (-not $templateRepo) {
            Write-LogSimple -Message "Template repository '$TemplateRepositoryName' not found. Creating empty repository and importing cache if available." -Type "WARNING"
        }

        $newRepo = New-RDMVault -Name $NewRepositoryName -ErrorAction Stop -IsAllowedOffline $true -VaultContentType "Everything"
        if (-not $newRepo) {
            $newRepo = Get-RDMRepository -ErrorAction Stop | Where-Object { $_.Name -eq $NewRepositoryName } | Select-Object -First 1
        }
        if (-not $newRepo) { throw "Repository '$NewRepositoryName' could not be created or resolved." }
        Set-RDMCurrentRepository -Repository $newRepo -ErrorAction Stop

        if ($TemplateExportFile -and (Test-Path $TemplateExportFile)) {
            Write-LogSimple -Message "Importing template cache '$TemplateExportFile'." -Type "INFO"
            Import-RDMSession -Path $TemplateExportFile -Set -ErrorAction Stop `
                -ForcePromptAnswer ([System.Windows.Forms.DialogResult]::Yes) -DuplicateAction "Overwrite"
        } else {
            Write-LogSimple -Message "No template cache provided. Run single export/import flow if needed." -Type "WARNING"
        }

        Write-LogSimple -Message "Template applied to '$NewRepositoryName'." -Type "INFO"
    } catch {
        Write-LogSimple -Message "Error while cloning template: $($_.Exception.Message)" -Type "ERROR"
        $existingRepo = Get-RDMRepository -ErrorAction SilentlyContinue | Where-Object { $_.Name -eq $NewRepositoryName } | Select-Object -First 1
        if (-not $existingRepo) {
            New-RDMVault -Name $NewRepositoryName -ErrorAction Stop -IsAllowedOffline $true -VaultContentType "Everything" | Out-Null
        }
        throw
    }
}

And here how I call it:

try {
    $appId = $ScriptConfig.ApplicationId
    $appSecretPath = $ScriptConfig.ApplicationSecretFile
    if ([string]::IsNullOrWhiteSpace($appId)) {
        throw "ApplicationId must be configured."
    }
    if ([string]::IsNullOrWhiteSpace($appSecretPath) -or -not (Test-Path $appSecretPath)) {
        throw "ApplicationSecret file missing: $appSecretPath"
    }
    $appSecret = (Get-Content -Path $appSecretPath -Raw).Trim()
    if ([string]::IsNullOrWhiteSpace($appSecret)) {
        throw "ApplicationSecret file is empty: $appSecretPath"
    }

    if ($OverrideOptionFilePath) {
        $optionDir = Split-Path $OverrideOptionFilePath -Parent
        if ($optionDir -and -not (Test-Path $optionDir)) {
            New-Item -ItemType Directory -Path $optionDir -Force | Out-Null
        }
        $override = Get-RDMPowerShellOverride
        $override.OptionFilePath = $OverrideOptionFilePath
        Set-RDMPowerShellOverride
    }

    Write-LogSimple -Message "Connecting to $DvlsUrl with application id '$appId'..." -Type "INFO"

    $ds = New-RDMDataSource -DVLS -Name $ScriptConfig.DataSourceName -Server $DvlsUrl -ScriptingTenantID $appId -ScriptingApplicationPassword $appSecret -SetDatasource -WarningAction SilentlyContinue
    Set-RDMDataSource $ds
    Set-RDMCurrentDataSource $ds

    $templateCache = Get-TemplateExport -TemplateRepositoryName $ScriptConfig.TemplateRepositoryName `
        -TemplateExportPath $ScriptConfig.TemplateExportPath `
        -Force:$ScriptConfig.ForceTemplateExport

    if (-not $templateCache) { throw "Template export unavailable; aborting repository creation." }

    $newRepoName = "{0}_{1}" -f $CustomerNo.Trim(), $CustomerName.Trim()
    Write-LogSimple -Message "Target repository: $newRepoName" -Type "INFO"

    try {
        $existingRepo = Get-RDMRepository -ErrorAction Stop | Where-Object { $_.Name -eq $newRepoName } | Select-Object -First 1
    } catch {
        $existingRepo = $null
    }

    if ($existingRepo) {
        Write-LogSimple -Message "Repository '$newRepoName' already exists (ID: $($existingRepo.ID)). Skipping creation." -Type "WARNING"
        return
    }

    if (-not $PSCmdlet.ShouldProcess($newRepoName, "Create repository from template '$($ScriptConfig.TemplateRepositoryName)'")) {
        Write-LogSimple -Message "Creation of '$newRepoName' would run." -Type "WHATIF"
        return
    }

    New-RepositoryFromTemplate -NewRepositoryName $newRepoName `
        -TemplateRepositoryName $ScriptConfig.TemplateRepositoryName `
        -TemplateExportFile $templateCache

    Add-CreatedRepository -RepositoryName $newRepoName

    Write-LogSimple -Message "Repository '$newRepoName' created from template '$($ScriptConfig.TemplateRepositoryName)'." -Type "ACTION"
} catch {
    Write-LogSimple -Message "Error during repository creation: $($_.Exception.Message)" -Type "ERROR"
    Write-LogSimple -Message "Details: $($_.ToString())" -Type "ERROR"
} finally {
    Close-DSSession | Out-Null
} 
avatar

Hello @kiaarmani,

For New-RDMVault to automatically save the created vault, the -SetRepository switch parameter is necessary.

Best regards,
Christian Robert

avatar

Hello there!

That worked, thank you!

avatar

It appears I have the same issue with Add-RDMRoleRepositoryAccess. It claims to have done it, but it actually didn't. I checked the Get-Help output for possible missing arguments, but did not find anything. I feel like I am overseeing something here again. Do I need to re-save the repo?

function Grant-RepositoryRoles {
    param (
        [Parameter(Mandatory = $true)] [psobject]$Repository,
        [string[]]$RoleNames
    )

    if (-not $Repository) { throw "Repository reference missing for role assignment." }
    $roles = $RoleNames | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | ForEach-Object { $_.Trim() } | Where-Object { $_ }

    if (-not $roles -or $roles.Count -eq 0) {
        Write-LogSimple -Message "No repository roles configured; skipping role assignment." -Type "INFO"
        return
    }

    try {
        $addAccessCmd = Get-Command Add-RDMRoleRepositoryAccess -ErrorAction SilentlyContinue
        if (-not $addAccessCmd) { throw "Add-RDMRoleRepositoryAccess command not available to assign roles." }

        Set-RDMCurrentRepository -Repository $Repository -ErrorAction SilentlyContinue | Out-Null
        Write-LogSimple -Message ("Assigning roles to repository '{0}' (ID: {1}; Type: {2})" -f $Repository.Name, $Repository.ID, $Repository.GetType().FullName) -Type "DEBUG"

        $resolvedRoles = New-Object System.Collections.Generic.List[object]
        foreach ($roleName in $roles) {
            $roleObj = $null
            Write-LogSimple -Message ("Resolving role '{0}'..." -f $roleName) -Type "DEBUG"
            try {
                if (Get-Command Get-RDMRole -ErrorAction SilentlyContinue) {
                    $roleObj = Get-RDMRole -Name $roleName -ErrorAction Stop | Select-Object -First 1
                }
            } catch { $roleObj = $null }

            if (-not $roleObj) {
                $available = @()
                try { $available = (Get-RDMRole -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Name) } catch { }
                Write-LogSimple -Message ("Role '{0}' not found. Available roles: {1}" -f $roleName, ($available -join ", ")) -Type "ERROR"
                throw "Role '$roleName' not found; cannot grant repository access."
            }

            Add-RDMRoleRepositoryAccess -Repository $Repository -Role $roleObj -ForcePromptAnswer ([System.Windows.Forms.DialogResult]::Yes) -ErrorAction Stop | Out-Null
            Set-RDMRole -Role $roleObj -ForcePromptAnswer ([System.Windows.Forms.DialogResult]::Yes) -ErrorAction Stop | Out-Null
            $resolvedRoles.Add($roleObj.Name) | Out-Null
            Write-LogSimple -Message ("Role '{0}' granted repository access." -f $roleObj.Name) -Type "DEBUG"
        }

        Write-LogSimple -Message ("Roles granted to repository '{0}': {1}" -f $Repository.Name, ($resolvedRoles -join ", ")) -Type "INFO"
    } catch {
        Write-LogSimple -Message ("Failed to assign repository roles: {0}" -f $_.Exception.Message) -Type "ERROR"
        throw
    }
}


Output:

[INFO] Connecting to https://REDACTED with application id 'REDACTED'...
[INFO] Target repository: 999999_Acme Corp
[DEBUG] Assigning roles to repository '999999_Acme Corp' (ID: REDACTED; Type: RemoteDesktopManager.PowerShellModule.PSOutputObject.PSRepositoryInfo)
[DEBUG] Resolving role 'ROLE_01'...
[DEBUG] Role 'ROLE_02' granted repository access.
[DEBUG] Resolving role 'ROLE_02'...
[DEBUG] Role 'ROLE_02' granted repository access.
[INFO] Roles granted to repository '999999_Acme Corp': ROLE_01, ROLE_02
avatar

Hello @kiaarmani,

I believe your Set-RDMRole call is "resetting" your role's information to a previous state which doesn't have the appropriate vault assignment. If the only modification you're trying to make to the role is to give it access to the vault, you can remove Set-RDMRole; Add-RDMRoleRepositoryAccess should work in itself.

Best regards,
Christian

avatar

Hello @Christian Robert,

I have removed the call and ran the script again and it works! Thank you!