checkpoint
This commit is contained in:
Родитель
ce6f23fac8
Коммит
7b3bc789f1
37
build.ps1
37
build.ps1
|
@ -87,23 +87,52 @@ function CleanUp() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function StartTest() {
|
function StartTest() {
|
||||||
|
$group = GetGlobalVariable IIS_ADMIN_API_OWNERS
|
||||||
|
$member = & ([System.IO.Path]::Combine($scriptDir, "setup", "security.ps1")) CurrentAdUser
|
||||||
|
if (!(Get-LocalGroupMember -Group $group -Member $member -ErrorAction SilentlyContinue)) {
|
||||||
|
Add-LocalGroupMember -Group $group -Member $member
|
||||||
|
}
|
||||||
$pingEndpoint = "https://localhost:$testPort"
|
$pingEndpoint = "https://localhost:$testPort"
|
||||||
try {
|
try {
|
||||||
Invoke-WebRequest $pingEndpoint | Out-Null
|
Invoke-WebRequest -UseDefaultCredentials -UseBasicParsing $pingEndpoint | Out-Null
|
||||||
} catch {
|
} catch {
|
||||||
Write-Error "Failed to ping test server $pingEndpoint, did you forget to start it manually?"
|
Write-Error "Failed to ping test server $pingEndpoint, did you forget to start it manually?"
|
||||||
Exit 1
|
Exit 1
|
||||||
}
|
}
|
||||||
## do the real test
|
}
|
||||||
|
|
||||||
|
function VerifyPath($path) {
|
||||||
|
if (!(Test-Path $path)) {
|
||||||
|
Write-Path "$path does not exist"
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
|
||||||
|
function VerifyPrecondition() {
|
||||||
|
if (!(VerifyPath [System.IO.Path]::Combine($projectRoot, "test", "appsettings.test.json")) `
|
||||||
|
-or !(VerifyPath [System.IO.Path]::Combine($projectRoot, "test", "Microsoft.IIS.Administration.Tests", "test.config.json.template"))) {
|
||||||
|
throw "Test configurations do no exist, run .\scripts\Configure-DevEnvironment.ps1 -ConfigureTestEnvironment"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function GetGlobalVariable($name) {
|
||||||
|
& ([System.IO.Path]::Combine($scriptDir, "setup", "globals.ps1")) $name
|
||||||
}
|
}
|
||||||
|
|
||||||
########################################################### Main Script ##################################################################
|
########################################################### Main Script ##################################################################
|
||||||
|
|
||||||
$scriptDir = Join-Path $PSScriptRoot "scripts"
|
try {
|
||||||
|
$projectRoot = git rev-parse --show-toplevel
|
||||||
|
} catch {
|
||||||
|
Write-Warning "Error looking for project root $_, using script location instead"
|
||||||
|
$projectRoot = $PSScriptRoot
|
||||||
|
}
|
||||||
|
$scriptDir = Join-Path $projectRoot "scripts"
|
||||||
# publish script only takes full path
|
# publish script only takes full path
|
||||||
$publishPath = ForceResolvePath "$publishPath"
|
$publishPath = ForceResolvePath "$publishPath"
|
||||||
$installPath = ForceResolvePath "$installPath"
|
$installPath = ForceResolvePath "$installPath"
|
||||||
$serviceName = & ([System.IO.Path]::Combine($scriptDir, "setup", "globals.ps1")) DEFAULT_SERVICE_NAME
|
$serviceName = GetGlobalVariable DEFAULT_SERVICE_NAME
|
||||||
|
|
||||||
Write-Host "[Build] Starting clean up..."
|
Write-Host "[Build] Starting clean up..."
|
||||||
CleanUp
|
CleanUp
|
||||||
|
|
|
@ -252,9 +252,9 @@ function Set-Acls($_path) {
|
||||||
[System.Security.AccessControl.PropagationFlags]::None,
|
[System.Security.AccessControl.PropagationFlags]::None,
|
||||||
[System.Security.AccessControl.AccessControlType]::Allow)
|
[System.Security.AccessControl.AccessControlType]::Allow)
|
||||||
|
|
||||||
$administratorsModify = New-Object System.Security.AccessControl.FileSystemAccessRule(
|
$administratorsRead = New-Object System.Security.AccessControl.FileSystemAccessRule(
|
||||||
$administrators,
|
$administrators,
|
||||||
[System.Security.AccessControl.FileSystemRights]::Modify,
|
[System.Security.AccessControl.FileSystemRights]::ReadAndExecute,
|
||||||
[System.Security.AccessControl.InheritanceFlags]"ContainerInherit,ObjectInherit",
|
[System.Security.AccessControl.InheritanceFlags]"ContainerInherit,ObjectInherit",
|
||||||
[System.Security.AccessControl.PropagationFlags]::None,
|
[System.Security.AccessControl.PropagationFlags]::None,
|
||||||
[System.Security.AccessControl.AccessControlType]::Allow)
|
[System.Security.AccessControl.AccessControlType]::Allow)
|
||||||
|
@ -281,7 +281,7 @@ function Set-Acls($_path) {
|
||||||
$acl.Access | Foreach-Object { $acl.RemoveAccessRule($_) }
|
$acl.Access | Foreach-Object { $acl.RemoveAccessRule($_) }
|
||||||
$acl.AddAccessRule($currentUserRead)
|
$acl.AddAccessRule($currentUserRead)
|
||||||
$acl.AddAccessRule($trustedInstallerFullControl)
|
$acl.AddAccessRule($trustedInstallerFullControl)
|
||||||
$acl.AddAccessRule($administratorsModify)
|
$acl.AddAccessRule($administratorsRead)
|
||||||
$acl.AddAccessRule($systemRead)
|
$acl.AddAccessRule($systemRead)
|
||||||
# Update the folder to use the new ACL
|
# Update the folder to use the new ACL
|
||||||
Set-Acl -Path $_path -AclObject $acl
|
Set-Acl -Path $_path -AclObject $acl
|
||||||
|
@ -293,7 +293,7 @@ function Set-Acls($_path) {
|
||||||
# Remove all existing access rules
|
# Remove all existing access rules
|
||||||
$acl.Access | Foreach-Object { $acl.RemoveAccessRule($_) }
|
$acl.Access | Foreach-Object { $acl.RemoveAccessRule($_) }
|
||||||
$acl.AddAccessRule($currentUserRead)
|
$acl.AddAccessRule($currentUserRead)
|
||||||
$acl.AddAccessRule($administratorsModify)
|
$acl.AddAccessRule($administratorsRead)
|
||||||
$acl.AddAccessRule($trustedInstallerFullControl)
|
$acl.AddAccessRule($trustedInstallerFullControl)
|
||||||
$acl.AddAccessRule($systemFullControl)
|
$acl.AddAccessRule($systemFullControl)
|
||||||
# Update the folder to use the new ACL
|
# Update the folder to use the new ACL
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
<AssemblyName>Microsoft.IIS.Administration</AssemblyName>
|
<AssemblyName>Microsoft.IIS.Administration</AssemblyName>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<PackageId>Microsoft.IIS.Administration</PackageId>
|
<PackageId>Microsoft.IIS.Administration</PackageId>
|
||||||
|
<IsTransformWebConfigDisabled>true</IsTransformWebConfigDisabled>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -41,6 +42,7 @@
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Antiforgery" Version="2.1.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Antiforgery" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.1.2" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.1.2" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.1.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.1.1" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Hosting.WindowsServices" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.1.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Server.HttpSys" Version="2.1.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Server.HttpSys" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.1.1" />
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.1.1" />
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
namespace Microsoft.IIS.Administration {
|
namespace Microsoft.IIS.Administration {
|
||||||
using AspNetCore.Builder;
|
using AspNetCore.Builder;
|
||||||
using AspNetCore.Hosting;
|
using AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Hosting.WindowsServices;
|
||||||
using Microsoft.AspNetCore.Server.HttpSys;
|
using Microsoft.AspNetCore.Server.HttpSys;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.IIS.Administration.WindowsService;
|
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
public class Program {
|
public class Program {
|
||||||
|
@ -45,8 +45,7 @@ namespace Microsoft.IIS.Administration {
|
||||||
//
|
//
|
||||||
// Run as a Service
|
// Run as a Service
|
||||||
Log.Information($"Running as service: {serviceName}");
|
Log.Information($"Running as service: {serviceName}");
|
||||||
new ServiceHelper(serviceName).Run(token => host.RunAsync(token))
|
host.RunAsService();
|
||||||
.Wait();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//
|
//
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
|
|
||||||
namespace Microsoft.IIS.Administration.WindowsService {
|
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
|
|
||||||
static class Interop {
|
|
||||||
private const string SERVICE_CORE_API_SET = "api-ms-win-service-core-l1-1-0";
|
|
||||||
|
|
||||||
public const int SERVICE_TYPE_WIN32_OWN_PROCESS = 0x00000010;
|
|
||||||
public const int SERVICE_TYPE_WIN32_SHARE_PROCESS = 0x00000020;
|
|
||||||
public const int SERVICE_TYPE_WIN32 = SERVICE_TYPE_WIN32_OWN_PROCESS | SERVICE_TYPE_WIN32_SHARE_PROCESS;
|
|
||||||
|
|
||||||
public const int SERVICE_CONTROL_STOP = 0x00000001;
|
|
||||||
public const int SERVICE_ACCEPT_STOP = 0x00000001;
|
|
||||||
|
|
||||||
public const int SERVICE_STOPPED = 0x00000001;
|
|
||||||
public const int SERVICE_START_PENDING = 0x00000002;
|
|
||||||
public const int SERVICE_STOP_PENDING = 0x00000003;
|
|
||||||
public const int SERVICE_RUNNING = 0x00000004;
|
|
||||||
public const int SERVICE_CONTINUE_PENDING = 0x00000005;
|
|
||||||
public const int SERVICE_PAUSE_PENDING = 0x00000006;
|
|
||||||
public const int SERVICE_PAUSED = 0x00000007;
|
|
||||||
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct SERVICE_STATUS {
|
|
||||||
public int serviceType;
|
|
||||||
public int currentState;
|
|
||||||
public int controlsAccepted;
|
|
||||||
public int win32ExitCode;
|
|
||||||
public int serviceSpecificExitCode;
|
|
||||||
public int checkPoint;
|
|
||||||
public int waitHint;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public class SERVICE_TABLE_ENTRY {
|
|
||||||
public IntPtr name;
|
|
||||||
public Delegate callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport(SERVICE_CORE_API_SET, CharSet = CharSet.Unicode, SetLastError = true)]
|
|
||||||
public extern static IntPtr RegisterServiceCtrlHandlerExW(string serviceName, Delegate callback, IntPtr userData);
|
|
||||||
|
|
||||||
[DllImport(SERVICE_CORE_API_SET, CharSet = CharSet.Unicode, SetLastError = true)]
|
|
||||||
public extern static bool SetServiceStatus(IntPtr serviceHandle, ref SERVICE_STATUS status);
|
|
||||||
|
|
||||||
[DllImport(SERVICE_CORE_API_SET, CharSet = CharSet.Unicode, SetLastError = true)]
|
|
||||||
public extern static bool StartServiceCtrlDispatcherW(IntPtr entry);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,215 +0,0 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
|
|
||||||
|
|
||||||
namespace Microsoft.IIS.Administration.WindowsService {
|
|
||||||
using System;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Runtime.ExceptionServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
|
|
||||||
sealed class ServiceHelper {
|
|
||||||
private const uint ERROR_MORE_DATA = 0xEA;
|
|
||||||
private const int PENDING_TIMEOUT = 4000; // Timeout in ms during starting/stopping
|
|
||||||
|
|
||||||
private delegate int SvcCtrlHandlerEx(int control, int eventType, IntPtr eventData, IntPtr eventContext);
|
|
||||||
private delegate void SvcMainHandler(int argCount, IntPtr args);
|
|
||||||
|
|
||||||
private string _serviceName;
|
|
||||||
private Task _svcInitTask;
|
|
||||||
private CancellationTokenSource _cancellationToken = new CancellationTokenSource();
|
|
||||||
private IntPtr _serviceHandle = IntPtr.Zero;
|
|
||||||
|
|
||||||
SvcMainHandler _svcMainHandler;
|
|
||||||
SvcCtrlHandlerEx _svcCtrlHandlerEx;
|
|
||||||
|
|
||||||
class TaskState {
|
|
||||||
public ExceptionDispatchInfo Exception { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public ServiceHelper(string serviceName) {
|
|
||||||
if (string.IsNullOrEmpty(serviceName)) {
|
|
||||||
throw new ArgumentNullException(nameof(serviceName));
|
|
||||||
}
|
|
||||||
|
|
||||||
_serviceName = serviceName;
|
|
||||||
_svcMainHandler = new SvcMainHandler(SvcMain);
|
|
||||||
_svcCtrlHandlerEx = new SvcCtrlHandlerEx(SvcCtrlHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsService {
|
|
||||||
get {
|
|
||||||
return !string.IsNullOrEmpty(_serviceName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ServiceName {
|
|
||||||
get {
|
|
||||||
return _serviceName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Run(Action<CancellationToken> action) {
|
|
||||||
if (action == null) {
|
|
||||||
throw new ArgumentNullException(nameof(action));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsService) {
|
|
||||||
throw new InvalidOperationException("The process is not running as Windows Service");
|
|
||||||
}
|
|
||||||
|
|
||||||
await EnsureInit();
|
|
||||||
|
|
||||||
await Task.Run(()=> action(_cancellationToken.Token));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task EnsureInit() {
|
|
||||||
if (_svcInitTask != null) {
|
|
||||||
return _svcInitTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
_svcInitTask = CreateInitTask();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Start StartServiceCtrlDispatcher
|
|
||||||
Task.Run(() => {
|
|
||||||
IntPtr namePtr = Marshal.StringToHGlobalUni(ServiceName);
|
|
||||||
|
|
||||||
try {
|
|
||||||
//
|
|
||||||
// Build SERVICE_TABLE_ENTRY[2] table
|
|
||||||
IntPtr ptr = Marshal.AllocHGlobal(2 * Marshal.SizeOf<Interop.SERVICE_TABLE_ENTRY>());
|
|
||||||
|
|
||||||
Marshal.StructureToPtr(new Interop.SERVICE_TABLE_ENTRY() { callback = _svcMainHandler, name = namePtr }, ptr, true);
|
|
||||||
Marshal.StructureToPtr(new Interop.SERVICE_TABLE_ENTRY() { callback = null, name = IntPtr.Zero },
|
|
||||||
new IntPtr(ptr.ToInt64() + Marshal.SizeOf<Interop.SERVICE_TABLE_ENTRY>()), true);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Blocks until the Windows Service stops
|
|
||||||
if (!Interop.StartServiceCtrlDispatcherW(ptr)) {
|
|
||||||
throw new Win32Exception();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
CompleteInitTask(e);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
Marshal.FreeHGlobal(namePtr);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return _svcInitTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void SvcMain(int argCount, IntPtr args) {
|
|
||||||
try {
|
|
||||||
//
|
|
||||||
// Register the handler function for the service
|
|
||||||
_serviceHandle = Interop.RegisterServiceCtrlHandlerExW(ServiceName, _svcCtrlHandlerEx, IntPtr.Zero);
|
|
||||||
if (_serviceHandle == IntPtr.Zero) {
|
|
||||||
throw new Win32Exception();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Report Starting
|
|
||||||
SetStatus(Interop.SERVICE_START_PENDING);
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Do some startup logic here...
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Report Running
|
|
||||||
SetStatus(Interop.SERVICE_RUNNING);
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
//
|
|
||||||
CompleteInitTask(null);
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Wait for stop event
|
|
||||||
_cancellationToken.Token.WaitHandle.WaitOne();
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
CompleteInitTask(e);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
//
|
|
||||||
// Report Stopped
|
|
||||||
SetStatus(Interop.SERVICE_STOPPED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private int SvcCtrlHandler(int command, int eventType, IntPtr eventData, IntPtr eventContext) {
|
|
||||||
//
|
|
||||||
// Handle service control operation
|
|
||||||
switch (command) {
|
|
||||||
case Interop.SERVICE_CONTROL_STOP:
|
|
||||||
SetStatus(Interop.SERVICE_STOP_PENDING);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Signal the service to stop
|
|
||||||
_cancellationToken.Cancel();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetStatus(int state, int error = 0) {
|
|
||||||
if (_serviceHandle == IntPtr.Zero) {
|
|
||||||
throw new ArgumentNullException(nameof(_serviceHandle));
|
|
||||||
}
|
|
||||||
|
|
||||||
var status = new Interop.SERVICE_STATUS() {
|
|
||||||
currentState = state,
|
|
||||||
win32ExitCode = error,
|
|
||||||
serviceType = Interop.SERVICE_TYPE_WIN32_OWN_PROCESS,
|
|
||||||
controlsAccepted = (state == Interop.SERVICE_START_PENDING) ? 0 : Interop.SERVICE_ACCEPT_STOP,
|
|
||||||
waitHint = (state == Interop.SERVICE_START_PENDING) || (state == Interop.SERVICE_STOP_PENDING) ? PENDING_TIMEOUT : 0
|
|
||||||
};
|
|
||||||
|
|
||||||
Interop.SetServiceStatus(_serviceHandle, ref status); // Ignore errors
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task CreateInitTask() {
|
|
||||||
return new Task(s => {
|
|
||||||
var state = (TaskState)s;
|
|
||||||
|
|
||||||
if (state.Exception != null) {
|
|
||||||
state.Exception.Throw();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new TaskState());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CompleteInitTask(Exception e) {
|
|
||||||
if (_svcInitTask.Status != TaskStatus.Created) {
|
|
||||||
return; // The task has been started already
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Fail the task
|
|
||||||
if (e != null) {
|
|
||||||
((TaskState)_svcInitTask.AsyncState).Exception = ExceptionDispatchInfo.Capture(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
_svcInitTask.Start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
{
|
||||||
|
"host_id": "",
|
||||||
|
"host_name": "IIS Administration API",
|
||||||
|
"urls": "https://*:44326",
|
||||||
|
"security": {
|
||||||
|
"require_windows_authentication": true,
|
||||||
|
"users": {
|
||||||
|
"administrators": [
|
||||||
|
"IIS Administrators",
|
||||||
|
"IIS Administration API Owners"
|
||||||
|
],
|
||||||
|
"owners": [
|
||||||
|
"IIS Administration API Owners"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"access_policy": {
|
||||||
|
"api": {
|
||||||
|
"users": "administrators",
|
||||||
|
"access_key": true
|
||||||
|
},
|
||||||
|
"api_keys": {
|
||||||
|
"users": "administrators",
|
||||||
|
"access_key": false
|
||||||
|
},
|
||||||
|
"system": {
|
||||||
|
"users": "owners",
|
||||||
|
"access_key": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"logging": {
|
||||||
|
"enabled": true,
|
||||||
|
"file_name": "iis-admin-api-test-{Date}.txt",
|
||||||
|
"min_level": "Information",
|
||||||
|
"path": "%temp%\\iis-admin-api\\"
|
||||||
|
},
|
||||||
|
"auditing": {
|
||||||
|
"enabled": true,
|
||||||
|
"file_name": "audit-{Date}.txt",
|
||||||
|
"path": null
|
||||||
|
},
|
||||||
|
"cors": {
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"origin": "https://manage.iis.net",
|
||||||
|
"allow": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"files": {
|
||||||
|
"locations": [
|
||||||
|
{
|
||||||
|
"alias": "inetpub",
|
||||||
|
"path": "%systemdrive%\\inetpub",
|
||||||
|
"claims": [
|
||||||
|
"read",
|
||||||
|
"write"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": "tests",
|
||||||
|
"path": "D:\\GitHub\\Microsoft\\IIS.Administration\\.test",
|
||||||
|
"claims": [
|
||||||
|
"read",
|
||||||
|
"write"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче