Commit eb93e563 authored by Jason Williams's avatar Jason Williams Committed by GitHub
Browse files

Merge pull request #101 from WilliamsJason/master

Update mock generator and xbox test app.
parents efbc8675 abfa301b
Loading
Loading
Loading
Loading
+0 −176
Original line number Diff line number Diff line
//----------------------------------------------------------------------------------------------
// <copyright file="DevicePortalConnection.cs" company="Microsoft Corporation">
//     Licensed under the MIT License. See LICENSE.TXT in the project root license information.
// </copyright>
//----------------------------------------------------------------------------------------------

using System;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text.RegularExpressions;
using Microsoft.Tools.WindowsDevicePortal;
using static Microsoft.Tools.WindowsDevicePortal.DevicePortal;

namespace MockDataGenerator
{
    /// <summary>
    /// IDevicePortalConnection implementation for MockDataGenerator test project
    /// </summary>
    public class DevicePortalConnection : IDevicePortalConnection
    {
        /// <summary>
        /// Device Certificate
        /// </summary>
        private X509Certificate2 deviceCertificate = null;

        /// <summary>
        /// Initializes a new instance of the <see cref="DevicePortalConnection"/> class.
        /// </summary>
        /// <param name="address">device identifier</param>
        /// <param name="userName">WDP username</param>
        /// <param name="password">WDP password</param>
        public DevicePortalConnection(
            string address,
            string userName,
            string password)
        {
            this.Connection = new Uri(string.Format("https://{0}", address));
            this.Credentials = new NetworkCredential(userName, password);
        }

        /// <summary>
        /// Gets Connection property
        /// </summary>
        public Uri Connection
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets Web Socket Connection property
        /// </summary>
        public Uri WebSocketConnection
        {
            get
            {
                if (this.Connection == null)
                {
                    return null;
                }

                string absoluteUri = this.Connection.AbsoluteUri;

                if (absoluteUri.StartsWith("https", StringComparison.InvariantCultureIgnoreCase))
                {
                    return new Uri(Regex.Replace(absoluteUri, "https", "wss", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant));
                }
                else
                {
                    return new Uri(Regex.Replace(absoluteUri, "http", "ws", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant));
                }
            }
        }

        /// <summary>
        /// Gets Credentials property
        /// </summary>
        public NetworkCredential Credentials
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets or sets device family
        /// </summary>
        public string Family
        { 
            get; 
            set;
        }

        /// <summary>
        /// Gets or sets the device name
        /// </summary>
        public string Name
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets device OS Info
        /// </summary>
        public OperatingSystemInformation OsInfo
        {
            get;
            set;
        }

        /// <summary>
        /// Returns certificate data
        /// </summary>
        /// <returns>certificate data</returns>
        public byte[] GetDeviceCertificateData()
        {
            return this.deviceCertificate.GetRawCertData();
        }

        /// <summary>
        /// Validates and sets the device certificate.
        /// </summary>
        /// <param name="certificate">The device's root certificate.</param>
        public void SetDeviceCertificate(X509Certificate2 certificate)
        {
            if (!certificate.IssuerName.Name.Contains(DevicePortalCertificateIssuer))
            {
                throw new DevicePortalException(
                    (HttpStatusCode)0,
                    "Invalid certificate issuer",
                    null,
                    "Failed to download device certificate");
            }

            this.deviceCertificate = certificate;
        }

        /// <summary>
        /// Sets certificate data
        /// </summary>
        /// <param name="certificateData">certificate data</param>
        public void SetDeviceCertificate(byte[] certificateData)
        {
            X509Certificate2 cert = new X509Certificate2(certificateData);
            if (!cert.IssuerName.Name.Contains(DevicePortalCertificateIssuer))
            {
                throw new DevicePortalException(
                    (HttpStatusCode)0,
                    "Invalid certificate issuer",
                    null,
                    "Failed to download device certificate");
            }

            this.deviceCertificate = cert;
        }

        /// <summary>
        /// MockDataGenerator will never update the connection.
        /// </summary>
        /// <param name="requiresHttps">https required</param>
        public void UpdateConnection(bool requiresHttps)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        ///  MockDataGenerator will never update the connection.
        /// </summary>
        /// <param name="ipConfig">IP info</param>
        /// <param name="requiresHttps">https required</param>
        public void UpdateConnection(IpConfiguration ipConfig, bool requiresHttps)
        {
            throw new NotImplementedException();
        }
    }
}
+0 −1
Original line number Diff line number Diff line
@@ -44,7 +44,6 @@
    <Reference Include="System.Xml" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="DevicePortalConnection.cs" />
    <Compile Include="ParameterHelper.cs" />
    <Compile Include="Program.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
+1 −1
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@ namespace MockDataGenerator
        /// <summary>
        /// Device Identifier identifier string
        /// </summary>
        public static readonly string IpOrHostname = "ip";
        public static readonly string FullAddress = "address";

        /// <summary>
        /// WDP Username identifier string
+63 −28
Original line number Diff line number Diff line
@@ -26,22 +26,23 @@ namespace MockDataGenerator
        /// <summary>
        /// Usage string
        /// </summary>
        private const string GeneralUsageMessage = "Usage: /ip:<system-ip or hostname> /user:<WDP username> /pwd:<WDP password> [/endpoint:<api to call>] [/directory:<directory to save mock data file(s)>";
        private const string GeneralUsageMessage = "Usage: /address:<URL for device (eg. https://10.0.0.1:11443)> /user:<WDP username> /pwd:<WDP password> [/endpoint:<api to call>] [/directory:<directory to save mock data file(s)>";

        /// <summary>
        /// Endpoints for REST calls to populate
        /// Endpoints for REST calls to populate. Feel free to override this list (especially locally) to
        /// facilitate generating a large number of mock files all simultaneously.
        /// </summary>
        private static readonly string[] Endpoints = 
        {
            DevicePortal.DeviceFamilyApi,
            DevicePortal.MachineNameApi,
            DevicePortal.OsInfoApi,
            DevicePortal.XboxLiveUserApi,
            DevicePortal.XboxSettingsApi,
            DevicePortal.SystemPerfApi,
            DevicePortal.RunningProcessApi,
            WebSocketOpertionPrefix + DevicePortal.SystemPerfApi,
            WebSocketOpertionPrefix + DevicePortal.RunningProcessApi
        private static readonly Endpoint[] Endpoints = 
        {
            new Endpoint(HttpMethods.Get, DevicePortal.DeviceFamilyApi),
            new Endpoint(HttpMethods.Get, DevicePortal.MachineNameApi),
            new Endpoint(HttpMethods.Get, DevicePortal.OsInfoApi),
            new Endpoint(HttpMethods.Get, DevicePortal.XboxLiveUserApi),
            new Endpoint(HttpMethods.Get, DevicePortal.XboxSettingsApi),
            new Endpoint(HttpMethods.Get, DevicePortal.SystemPerfApi),
            new Endpoint(HttpMethods.Get, DevicePortal.RunningProcessApi),
            new Endpoint(HttpMethods.WebSocket, DevicePortal.SystemPerfApi),
            new Endpoint(HttpMethods.WebSocket, DevicePortal.RunningProcessApi),
        };

        /// <summary>
@@ -71,15 +72,15 @@ namespace MockDataGenerator
                return;
            }

            if (!parameters.HasParameter(ParameterHelper.IpOrHostname) || !parameters.HasParameter(ParameterHelper.WdpUser) || !parameters.HasParameter(ParameterHelper.WdpPassword))
            if (!parameters.HasParameter(ParameterHelper.FullAddress) || !parameters.HasParameter(ParameterHelper.WdpUser) || !parameters.HasParameter(ParameterHelper.WdpPassword))
            {
                Console.WriteLine("Missing one or more required parameter(s). Must provide ip, user, and pwd");
                Console.WriteLine("Missing one or more required parameter(s). Must provide address, user, and pwd");
                Console.WriteLine();
                Console.WriteLine(GeneralUsageMessage);
                return;
            }

            DevicePortalConnection connection = new DevicePortalConnection(parameters.GetParameterValue(ParameterHelper.IpOrHostname), parameters.GetParameterValue(ParameterHelper.WdpUser), parameters.GetParameterValue(ParameterHelper.WdpPassword));
            IDevicePortalConnection connection = new DefaultDevicePortalConnection(parameters.GetParameterValue(ParameterHelper.FullAddress), parameters.GetParameterValue(ParameterHelper.WdpUser), parameters.GetParameterValue(ParameterHelper.WdpPassword));
            DevicePortal portal = new DevicePortal(connection);

            Task connectTask = portal.Connect(updateConnection: false);
@@ -111,32 +112,30 @@ namespace MockDataGenerator
                Directory.CreateDirectory(directory);
            }


            if (parameters.HasParameter("endpoint"))
            {
                HttpMethods httpMethod = HttpMethods.Get;
                string endpoint = parameters.GetParameterValue("endpoint");

                if (endpoint.StartsWith(WebSocketOpertionPrefix, StringComparison.OrdinalIgnoreCase))
                if (parameters.HasParameter("method"))
                {
                    httpMethod = HttpMethods.WebSocket;
                    endpoint = endpoint.Substring(WebSocketOpertionPrefix.Length);
                    // This is case sensitive. Since it's only used while generating mocks which is a development time action,
                    // that seems okay. If we want to revisit I'd prefer keeping the casing of the enum and using a switch or
                    // if/else block to manually convert.
                    httpMethod = (HttpMethods)Enum.Parse(typeof(HttpMethods), parameters.GetParameterValue("method"));
                }

                string endpoint = parameters.GetParameterValue("endpoint");

                Task saveResponseTask = portal.SaveEndpointResponseToFile(endpoint, directory, httpMethod);
                saveResponseTask.Wait();
            }
            else
            {
                foreach (string endpoint in Endpoints)
                {
                    string finalEndpoint = endpoint;
                    HttpMethods httpMethod = HttpMethods.Get;

                    if (endpoint.StartsWith(WebSocketOpertionPrefix, StringComparison.OrdinalIgnoreCase))
                foreach (Endpoint endpoint in Endpoints)
                {
                        httpMethod = HttpMethods.WebSocket;
                        finalEndpoint = endpoint.Substring(WebSocketOpertionPrefix.Length);
                    }
                    HttpMethods httpMethod = endpoint.Method;
                    string finalEndpoint = endpoint.Value;

                    try
                    {
@@ -159,5 +158,41 @@ namespace MockDataGenerator

            Console.WriteLine("Data generated in directory {0}. Please make sure to remove any personally identifiable information from the response(s) before adding them as mock responses.", directory);
        }

        /// <summary>
        /// Encapsulation of an endpoint and its HTTP method.
        /// </summary>
        private class Endpoint
        {
            /// <summary>
            /// Initializes a new instance of the <see cref="Endpoint"/> class.
            /// </summary>
            /// <param name="method">The HTTP method this endpoint should use.</param>
            /// <param name="endpoint">The actual endpoint.</param>
            public Endpoint(HttpMethods method, string endpoint)
            {
                this.Method = method;
                this.Value = endpoint;
            }

            /// <summary>
            /// Gets or sets the HTTP Method.
            /// </summary>
            public HttpMethods Method { get; set; }

            /// <summary>
            /// Gets or sets the endpoint value.
            /// </summary>
            public string Value { get; set; }

            /// <summary>
            /// Overridden ToString method.
            /// </summary>
            /// <returns>Human readable representation of an Endpoint.</returns>
            public override string ToString()
            {
                return this.Method.ToString() + " : " + this.Value;
            }
        }
    }
}
+50 −3
Original line number Diff line number Diff line
@@ -5,10 +5,12 @@
//----------------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text.RegularExpressions;
using Microsoft.Tools.WindowsDevicePortal;
using Windows.Security.Credentials;
using static Microsoft.Tools.WindowsDevicePortal.DevicePortal;

namespace XboxWdpDriver
@@ -26,9 +28,9 @@ namespace XboxWdpDriver
        /// <summary>
        /// Initializes a new instance of the <see cref="DevicePortalConnection"/> class.
        /// </summary>
        /// <param name="address">device identifier</param>
        /// <param name="userName">WDP username</param>
        /// <param name="password">WDP password</param>
        /// <param name="address">The ip address or hostname of the device we are connecting to.</param>
        /// <param name="userName">The WDP username.</param>
        /// <param name="password">The WDP password.</param>
        public DevicePortalConnection(
            string address,
            string userName,
@@ -36,6 +38,51 @@ namespace XboxWdpDriver
        {
            this.Connection = new Uri(string.Format("https://{0}:11443", address));
            this.Credentials = new NetworkCredential(userName, password);

            PasswordVault vault = new PasswordVault();

            try
            {
                // Remove any existing stored creds for this address and add these ones.
                foreach (var cred in vault.FindAllByResource(address))
                {
                    vault.Remove(cred);
                }
            }
            catch (Exception)
            {
                // Do nothing. This is expected if no credentials have been previously stored
            }

            vault.Add(new PasswordCredential(address, userName, password));
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="DevicePortalConnection"/> class.
        /// This version of the contructor can be used if WDP credentials are not provided,
        /// and should be used if they were previously persisted or are not needed.
        /// </summary>
        /// <param name="address">The ip address or hostname of the device we are connecting to.</param>
        public DevicePortalConnection(
            string address)
        {
            this.Connection = new Uri(string.Format("https://{0}:11443", address));

            try
            {
                PasswordVault vault = new PasswordVault();
                // Set the first stored cred as our network creds.
                IReadOnlyList<PasswordCredential> creds = vault.FindAllByResource(address);
                if (creds != null && creds.Count > 0)
                {
                    creds[0].RetrievePassword();
                    this.Credentials = new NetworkCredential(creds[0].UserName, creds[0].Password);
                }
            }
            catch (Exception)
            {
                // Do nothing. No credentials were stored. If they are needed, REST calls will fail with Unauthorized.
            }
        }

        /// <summary>
Loading