public async Task <bool> UpdateIpAddressForSubdomain(string hostedZoneId, string fqdn, string newIpAddress) { using (AmazonRoute53Client route53Client = GetAmazonRoute53Client()) { ListResourceRecordSetsResponse records = await route53Client.ListResourceRecordSetsAsync(new ListResourceRecordSetsRequest(hostedZoneId)); // Look for an A record matching the FQDN that was passed in ResourceRecordSet matchingRecordSet = records?.ResourceRecordSets.FirstOrDefault(prop => prop.Name == fqdn && prop.Type == RRType.A); if (matchingRecordSet != null && matchingRecordSet.ResourceRecords.Any()) { if (matchingRecordSet.ResourceRecords.First().Value != newIpAddress) { matchingRecordSet.ResourceRecords.First().Value = newIpAddress; ChangeBatch change = new ChangeBatch(); change.Changes.Add(new Change(ChangeAction.UPSERT, matchingRecordSet)); ChangeResourceRecordSetsResponse changeRequest = await route53Client.ChangeResourceRecordSetsAsync(new ChangeResourceRecordSetsRequest(hostedZoneId, change)); Log.Information("[Runtime = {StartTime}] Change request submitted to change subdomain {Subdomain} IP address to {IPAddress}.", Settings.StartTime, fqdn, newIpAddress); return(changeRequest.HttpStatusCode == System.Net.HttpStatusCode.OK); } else { Log.Information("[Runtime = {StartTime}] Subdomain {Subdomain} found, but the IP address was already {IPAddress}.", Settings.StartTime, fqdn, newIpAddress); } } return(false); } }
private static void UnmarshallResult(XmlUnmarshallerContext context, ChangeResourceRecordSetsResponse response) { int originalDepth = context.CurrentDepth; int targetDepth = originalDepth + 1; if (context.IsStartOfDocument) { targetDepth += 1; } while (context.Read()) { if (context.IsStartElement || context.IsAttribute) { if (context.TestExpression("ChangeInfo", targetDepth)) { var unmarshaller = ChangeInfoUnmarshaller.Instance; response.ChangeInfo = unmarshaller.Unmarshall(context); continue; } } else if (context.IsEndElement && context.CurrentDepth < originalDepth) { return; } } return; }
public void OnTimer(object sender, System.Timers.ElapsedEventArgs args) { eventLog.WriteEntry(LogMessaging.SERVICE_MONITORING, EventLogEntryType.Information); string date = Utility.GetRoute53Date(); string authValue = Utility.GetAWSR53_SHA1AuthorizationValue(Keys.ACCESS_KEY_ID, Keys.SECRET_KEY, date); string externalIp = Utility.GetExternalIp(); ListHostedZonesResponse listHostedZonesResponse = API.GetListHostedZones(date, authValue); var hostedZone = listHostedZonesResponse.HostedZones.Where(x => x.Name == "pierrethelusma.com.").SingleOrDefault(); ListResourceRecordSetsResponse listResourceRecordSetsResponse = API.GetListResourceRecordSets(date, authValue, hostedZone.Id); var resourceRecordSet = listResourceRecordSetsResponse.ResourceRecordSets.Where(x => x.Name == "home.pierrethelusma.com." && x.Type == "A").SingleOrDefault(); ChangeResourceRecordSetsResponse changeResourceRecordSetsResponse = new ChangeResourceRecordSetsResponse(); if (resourceRecordSet == null) { eventLog.WriteEntry(LogMessaging.SERVICE_CREATING_DNS_ENTRY, EventLogEntryType.Information); changeResourceRecordSetsResponse = API.PostChangeResourceRecordSets(date, authValue, externalIp, hostedZone.Id, "home.pierrethelusma.com.", "A", "600", "CREATE"); } else { if (!resourceRecordSet.ResourceRecords.Any(x => x.Value == externalIp)) { eventLog.WriteEntry(LogMessaging.SERVICE_UPDATING_DNS_ENTRY, EventLogEntryType.Information); changeResourceRecordSetsResponse = API.PostChangeResourceRecordSets(date, authValue, externalIp, hostedZone.Id, "home.pierrethelusma.com.", "A", "600", "UPSERT"); } } }
private async Task <ChangeResourceRecordSetsResponse> createAws_A_ResourceRecords(string hostedZoneId, string hostName) { ChangeBatch changes = new ChangeBatch(); string newHostName = hostName.Substring(0, hostName.Length - 1); logger.LogInformation($"Creating Alias Record for hosted zone { newHostName }..."); ResourceRecordSet aliasRs = new ResourceRecordSet() { AliasTarget = new AliasTarget() { HostedZoneId = "Z3AQBSTGFYJSTF", //use zone id from here: https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region DNSName = "s3-website-us-east-1.amazonaws.com", EvaluateTargetHealth = false }, Type = RRType.A, Name = newHostName }; Change AliasRecord = new Change(ChangeAction.CREATE, aliasRs); changes.Changes.Add(AliasRecord); ChangeResourceRecordSetsRequest request = new ChangeResourceRecordSetsRequest() { ChangeBatch = changes, HostedZoneId = hostedZoneId }; ChangeResourceRecordSetsResponse response = await TheRoute53Client().ChangeResourceRecordSetsAsync(request); return(response); }
/// <summary> /// Unmarshaller the response from the service to the response class. /// </summary> /// <param name="context"></param> /// <returns></returns> public override AmazonWebServiceResponse Unmarshall(XmlUnmarshallerContext context) { ChangeResourceRecordSetsResponse response = new ChangeResourceRecordSetsResponse(); UnmarshallResult(context, response); return(response); }
/// <summary> /// Create or change a DNS record for a hosted zone. /// </summary> /// <param name="hostedZoneId">The ID of the hosted zone that contains the resource record sets that you want to change</param> /// <param name="name">The name of the DNS record set.</param> /// <param name="type">The type of the DNS record set.</param> /// <param name="value">The value of the record set.</param> /// <param name="ttl">The time to live of the record set.</param> /// <param name="settings">The <see cref="Route53Settings"/> required to upload to Amazon S3.</param> /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param> public async Task <string> CreateResourceRecordSet(string hostedZoneId, string name, RRType type, string value, long ttl, Route53Settings settings, CancellationToken cancellationToken = default(CancellationToken)) { var recordSet = new ResourceRecordSet() { Name = name, TTL = ttl, Type = type, ResourceRecords = new List <ResourceRecord> { new ResourceRecord { Value = value } } }; var change1 = new Change() { ResourceRecordSet = recordSet, Action = ChangeAction.UPSERT }; var changeBatch = new ChangeBatch() { Changes = new List <Change> { change1 } }; var recordsetRequest = new ChangeResourceRecordSetsRequest() { HostedZoneId = hostedZoneId, ChangeBatch = changeBatch }; AmazonRoute53Client client = this.GetClient(settings); ChangeResourceRecordSetsResponse response = await client.ChangeResourceRecordSetsAsync(recordsetRequest); if (response.HttpStatusCode == HttpStatusCode.OK) { await this.WaitForChange(client, response.ChangeInfo.Id, 10000, 60); _Log.Verbose("Updated record set"); return(response.ChangeInfo.Id); } else { _Log.Error("Could not change resource records"); return(""); } }
internal void DeleteRecord(ResourceRecordSet s) { ChangeResourceRecordSetsResponse resp = myController.route53.ChangeResourceRecordSets(new ChangeResourceRecordSetsRequest() .WithHostedZoneId(this.ResponseData.Id) .WithChangeBatch(new ChangeBatch() .WithChanges( new Change() .WithAction("DELETE") .WithResourceRecordSet(s)))); Thread.Sleep(2000); UpdateInfo(); }
public override AmazonWebServiceResponse Unmarshall(XmlUnmarshallerContext context) { ChangeResourceRecordSetsResponse response = new ChangeResourceRecordSetsResponse(); while (context.Read()) { if (context.IsStartElement) { response.ChangeResourceRecordSetsResult = ChangeResourceRecordSetsResultUnmarshaller.GetInstance().Unmarshall(context); break; } } return(response); }
private async Task <ChangeResourceRecordSetsResponse> createAws_NS_ResourceRecords(string hostedZoneId, string fullName, ResourceRecordSet NsRecord) { logger.LogInformation($"Creating NS record for hosted zone ID { hostedZoneId }, { fullName }..."); ChangeBatch changes = new ChangeBatch(); Change change = new Change(ChangeAction.CREATE, NsRecord); changes.Changes.Add(change); ChangeResourceRecordSetsRequest request = new ChangeResourceRecordSetsRequest() { ChangeBatch = changes, HostedZoneId = hostedZoneId }; ChangeResourceRecordSetsResponse response = await TheRoute53Client().ChangeResourceRecordSetsAsync(request); return(response); }
private async static Task <bool> UpdateIpAddressForSubdomain(string hostedZoneId, string fqdn, string newIpAddress) { AmazonRoute53Config config = new AmazonRoute53Config() { RegionEndpoint = RegionEndpoint.GetBySystemName(Settings.AWSRegion) // TODO: inject }; using (AmazonRoute53Client route53Client = new AmazonRoute53Client(Settings.AWSAccessKeyId, Settings.AWSAccessKeySecret, config)) { ListResourceRecordSetsResponse records = await route53Client.ListResourceRecordSetsAsync(new ListResourceRecordSetsRequest(hostedZoneId)); ResourceRecordSet matchingRecordSet = records?.ResourceRecordSets.FirstOrDefault(prop => prop.Name == fqdn && prop.Type == RRType.A); if (matchingRecordSet != null && matchingRecordSet.ResourceRecords.FirstOrDefault() != null) { if (matchingRecordSet.ResourceRecords.FirstOrDefault().Value != newIpAddress) { matchingRecordSet.ResourceRecords.FirstOrDefault().Value = newIpAddress; ChangeBatch change = new ChangeBatch(); change.Changes.Add(new Change(ChangeAction.UPSERT, matchingRecordSet)); ChangeResourceRecordSetsResponse changeRequest = await route53Client.ChangeResourceRecordSetsAsync(new ChangeResourceRecordSetsRequest(hostedZoneId, change)); Log.Information("[Runtime = {StartTime}] Change request submitted to change subdomain {Subdomain} IP address to {IPAddress}.", startTime, fqdn, newIpAddress); return(changeRequest.HttpStatusCode == System.Net.HttpStatusCode.OK); } else { Log.Information("[Runtime = {StartTime}] Subdomain {Subdomain} found, but the IP address was already {IPAddress}.", startTime, fqdn, newIpAddress); } } else { // New subdomain Log.Information("[Runtime = {StartTime}] Subdomain {Subdomain} record not found.", startTime, fqdn); } return(false); } }
internal bool AddRecord(ResourceRecordSet s) { try { ChangeResourceRecordSetsResponse resp = myController.route53.ChangeResourceRecordSets(new ChangeResourceRecordSetsRequest() .WithHostedZoneId(this.ResponseData.Id) .WithChangeBatch(new ChangeBatch() .WithChanges( new Change() .WithAction("CREATE") .WithResourceRecordSet(s)))); Thread.Sleep(2000); UpdateInfo(); return(true); } catch (Exception ex) { Program.TraceLine("Failed adding a recordset, reason: ", ex); return(false); } }
public void SaveClients() { //Output Output($"MCS: Starting Save Clients"); string dataText = ""; //Validate if (Clients == null || !Clients.Any()) { //Output Output($"MCS: Had no Clients."); //Will update with an empty string - no clients } else { //Output Output($"MCS: Found {Clients.Count} Clients."); //1) Serialize to JSON text dataText = JsonConvert.SerializeObject(Clients); //2) Prepare the string (encrypt, compress) //Encrypt and Compress dataText = dataText.CompressThenEncrypt(Config.MultiClientSettings.Route53.EncryptionPassword); } //Add quotation marks dataText = "\"" + dataText + "\""; //3) Update to R53 //New the Route 53 Client AmazonRoute53Client r53Client = new AmazonRoute53Client( Config.BaseSettings.AWSAccessKeyID, Config.BaseSettings.AWSSecretAccessKey, new AmazonRoute53Config { RegionEndpoint = RegionEndpoint }); //New the Change Record to push Change change = new Change { Action = ChangeAction.UPSERT, //Insert or Update ResourceRecordSet = new ResourceRecordSet { Name = Config.MultiClientSettings.Route53.Name, TTL = 300, Type = RRType.TXT, ResourceRecords = new List <ResourceRecord> { new ResourceRecord(dataText) } } }; //New the Change Request ChangeResourceRecordSetsRequest recordSetsRequest = new ChangeResourceRecordSetsRequest { HostedZoneId = Config.MultiClientSettings.Route53.R53ZoneId, ChangeBatch = new ChangeBatch(new List <Change> { change }) }; //Submitting the Change Request to the API and receiving back the ID ChangeResourceRecordSetsResponse recordSetResponse = r53Client .ChangeResourceRecordSetsAsync(recordSetsRequest) .GetAwaiter() .GetResult(); //The ID of the response string changeId = recordSetResponse.ChangeInfo.Id; //Output Output($"MCS-R53: Change ID \"{changeId}\": ChangeRequest was submitted."); //Enquire with R53 the status of the change (R53 updates can be VERY slow business) GetChangeRequest changeRequest = new GetChangeRequest { Id = changeId }; while (r53Client.GetChangeAsync(changeRequest).GetAwaiter().GetResult().ChangeInfo.Status == ChangeStatus.PENDING) { //Output Output($"MCS-R53: Change ID \"{changeId}\": Change is still pending. (Can take a while.)"); //Wait Thread.Sleep(10 * 1000); //Wait ten seconds } //Output DONE Output($"MCS-R53: Change ID \"{changeId}\": Change IN SYNC. Done."); Output($"MCS: Completed Save of {Clients.Count} Clients"); }
/// <summary> /// Run a single item /// </summary> /// <param name="item">The item to run</param> public void RunItem(Route53Host item) { //Output Output($"R53: Starting item: {item}, new IP address: {IpState.NewIP}"); //New the Route 53 Client AmazonRoute53Client r53Client = new AmazonRoute53Client( Config.BaseSettings.AWSAccessKeyID, Config.BaseSettings.AWSSecretAccessKey, new AmazonRoute53Config { RegionEndpoint = RegionEndpoint }); //New the Change Record to push Change change = new Change { Action = ChangeAction.UPSERT, //Insert or Update ResourceRecordSet = new ResourceRecordSet { Name = item.Name, TTL = item.TTL, Type = RRType.A, ResourceRecords = new List <ResourceRecord> { new ResourceRecord(IpState.NewIP) } } }; //New the Change Request ChangeResourceRecordSetsRequest recordSetsRequest = new ChangeResourceRecordSetsRequest { HostedZoneId = item.ZoneId, ChangeBatch = new ChangeBatch(new List <Change> { change }) }; //Submitting the Change Request to the API and receiving back the ID ChangeResourceRecordSetsResponse recordSetResponse = r53Client.ChangeResourceRecordSetsAsync(recordSetsRequest).GetAwaiter().GetResult(); //The ID of the response string changeId = recordSetResponse.ChangeInfo.Id; //Output Output($"R53: Change ID \"{changeId}\": ChangeRequest was submitted."); //Enquire with R53 the status of the change (R53 updates can be VERY slow business) GetChangeRequest changeRequest = new GetChangeRequest { Id = changeId }; while (r53Client.GetChangeAsync(changeRequest).GetAwaiter().GetResult().ChangeInfo.Status == ChangeStatus.PENDING) { //Output Output($"R53: Change ID \"{changeId}\": Change is still pending. (Can take a while.)"); //Wait Thread.Sleep(10 * 1000); //Wait ten seconds } //Output DONE Output($"R53: Change ID \"{changeId}\": Change IN SYNC. Done."); }
/// <summary> /// This method does all of the work to update the DNS records with our current WAN IP. This is separated from the main /// method to make it easier in the future to perform batch updates (if needed). /// </summary> /// <param name="id">The AWS Access key ID</param> /// <param name="secret">The AWS Access key secret</param> /// <param name="domain">The domain name we are going to be updating records for (e.g. shawnlehner.com)</param> /// <param name="subdomain">The subdomain we would like to update (e.g. "house" if we were updating house.shawnlehner.com)</param> private static async Task PerformDnsUpdate(string id, string secret, string domain, string subdomain) { #region Lookup Current WAN IP // We use ipify.org to quickly/easily get our external WAN IP address which we can later use // for updating our DNS records. string ip = null; HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://api.ipify.org"); using (Stream s = (await request.GetResponseAsync()).GetResponseStream()) using (StreamReader r = new StreamReader(s)) { ip = r.ReadToEnd(); } #endregion // Combine our domain and subdomain to get the full record name string recordName = subdomain.Trim('.') + "." + domain.Trim('.'); // Create our AWS API client for sending requests to the Route53 API AmazonRoute53Client client = new AmazonRoute53Client(id, secret, RegionEndpoint.USEast1); #region Lookup current state of the domain on Route53 // Lookup the zone for our domain HostedZone zone = (await client.ListHostedZonesByNameAsync(new ListHostedZonesByNameRequest { DNSName = domain })).HostedZones.First(); // Lookup our current records to see if we need to make an update ListResourceRecordSetsResponse recordSet = await client.ListResourceRecordSetsAsync(new ListResourceRecordSetsRequest { HostedZoneId = zone.Id, MaxItems = "1", StartRecordName = recordName }); #endregion // Check to see if our IP is already up to date. No sense making a change if we don't need to. if (recordSet.ResourceRecordSets.Count > 0 && recordSet.ResourceRecordSets[0].Name.Trim('.') == recordName && recordSet.ResourceRecordSets[0].ResourceRecords[0].Value == ip) { return; } #region Request DNS record update with new IP // Our IP address is not up-to-date so we need to make a change request. We use UPSERT action which // will work whether or not a record already exists. ChangeResourceRecordSetsRequest changeRequest = new ChangeResourceRecordSetsRequest { HostedZoneId = zone.Id, ChangeBatch = new ChangeBatch { Changes = new List <Change> { new Change { ResourceRecordSet = new ResourceRecordSet { Name = recordName, TTL = 60, Type = RRType.A, ResourceRecords = new List <ResourceRecord> { new ResourceRecord { Value = ip } } }, Action = ChangeAction.UPSERT } } } }; // Send our change request to the API ChangeResourceRecordSetsResponse response = await client.ChangeResourceRecordSetsAsync(changeRequest); // Check our response code to verify everything worked if (response.HttpStatusCode != HttpStatusCode.OK) { throw new Exception("API request to update DNS record has failed."); } #endregion }
public static void Route53CreateAdd(string[] args) { #region Route53CreateAdd string domainName = "www.example.org"; IAmazonRoute53 route53Client = new AmazonRoute53Client(); CreateHostedZoneRequest zoneRequest = new CreateHostedZoneRequest { Name = domainName, CallerReference = "my_change_request" }; CreateHostedZoneResponse zoneResponse = route53Client.CreateHostedZone(zoneRequest); ResourceRecordSet recordSet = new ResourceRecordSet { Name = domainName, TTL = 60, Type = RRType.A, ResourceRecords = new List <ResourceRecord> { new ResourceRecord { Value = "192.0.2.235" } } }; Change change1 = new Change { ResourceRecordSet = recordSet, Action = ChangeAction.CREATE }; ChangeBatch changeBatch = new ChangeBatch { Changes = new List <Change> { change1 } }; ChangeResourceRecordSetsRequest recordsetRequest = new ChangeResourceRecordSetsRequest { HostedZoneId = zoneResponse.HostedZone.Id, ChangeBatch = changeBatch }; ChangeResourceRecordSetsResponse recordsetResponse = route53Client.ChangeResourceRecordSets(recordsetRequest); GetChangeRequest changeRequest = new GetChangeRequest { Id = recordsetResponse.ChangeInfo.Id }; while (route53Client.GetChange(changeRequest).ChangeInfo.Status == ChangeStatus.PENDING) { Console.WriteLine("Change is pending."); Thread.Sleep(TimeSpan.FromSeconds(15)); } #endregion Console.WriteLine("Change is complete."); Console.ReadKey(); }