Cloud Services Are Seriously Nickle And Diming Us To Death With Micro-Segmentation Of Common Services

I look at my Azure bill each month and cannot make heads or tails of it because each service I use in Azure is so broken down into such fine pieces that it makes no sense to me. I mean take a function, you pay for the memory it consumes, the CPU cycles it consumes, the bandwidth it consumes, and the total number of times it is executed each month. Come the fuck on! How much finer can you break a service down and charge separately for each component and then charge excessively for each component and then advertise it as a single item?

Seriously! I have spent the last month talking to Azure Sales, Microsoft Partner Solutions (I’m a partner I must admit), and Azure Billing trying to get an accurate quote for 4 C# functions executing 14,400,000 times a month consuming less than 128MB ram and using less than 512MB of bandwidth a month. After a month my answer is that no one CAN TELL ME! I was taken aback by that and told to try the pricing calculator after being told in a round-robin fashion to talk to so and so and then that person would refer me to another section and they would refer me back to another section that I had talked to two weeks earlier. It is just sad that they are billing this stuff and the people who are selling it and generating the billing statements don’t know how to generate a quote based on numbers calculated by their own pricing calculator LOL!

It all goes back to my post title, cloud companies have micro-segmented everything they sell down so far to their basic components and are charging outrageous prices for each and then advertising them as a whole package with no price tag on it. They just say, “Hey we got Serverless Functions! They’re easy to set up and use!” They don’t tell you that they are gonna bill you out the ass for each individual little piece that makes up the total function in that pitch or that they can’t honestly quote you an accurate price other than say get on a pricing plan and pray you don’t go over and end up paying Consumption Tier Pricing for going over your cap.

Apps are going the same way with micro-billing and features but I’m not going that way with mine. I’m going subscription in order to keep them updated and be able to keep my backends up to date and development environment current but I think I charge a reasonable price. That is what I am trying to do now with my upcoming app to bring the subscription cost down to a reasonable cost but Azure will literally eat 75% of the revenue generated from the individual subscription as it currently stands and I can’t bring the cost down enough to really make it more appealing to the end user. That is fucking sad.

Four C# functions should not cost $9500 a month for just an estimated 1000 users…… even when it takes them only 6 seconds to execute a task per user, per function…….ever…..

John

Synology DSM/SRM Blocked IP’s List – Updated August 16, 2024 (Added the few my VPS Honeypot gathered as well)

Hey there, folks! Just wanted to share my list of blocked IPs with you. These are the ones that have been trying to log into my SRM or DSM over time. You can download the list and add them to your own blocked addresses if you want to. It’s a great way to beef up your system security, you know? I make sure to update the list every couple of weeks or so. Why? Well, because there’s no shortage of these troublemakers trying to get in and mess with us. It’s like they’ve got nothing better to do! But hey, no worries, I’ve got your back. Right now, the list has an impressive count of around 8864 IPs. And guess what? It keeps growing! Yeah, every week it adds about 20 new ones to the mix. Can you believe it? That’s why it’s so important to keep building a solid wall against these sneaky intruders. So, let’s stay on our toes and keep updating that list. We’ll make sure our digital assets stay safe and sound, and keep those potential threats at bay. Stay strong, my friends!

Hey, if you’re interested, we’ve got this cool CR/LF format that you can easily import into your block list. You can compare it with your current list too. The great thing is, that it smoothly integrates with your existing block list. Plus, it’s smart enough to skip any duplicate entries, so no need to worry about pointless repetition. With this, your block list will stay super organized and efficient.

John

Configure Mobile.BuildTools in .NET MAUI to keep your secrets safe

I had some issues at first with compiling after doing my first migration from Xamarin to .NET MAUI with Mobile.BuildTools but I went back to some of mother other apps and found my old solution to a new problem.

The nuget works great in MAUI and I am more comfortable with it than some of the newer methods to keep secrets out of your source. So here is a quick overview of what it takes to configure it and get it working in your .NET MAUI or Xamarin app.

Understanding the configuration file for the nuget is key. There are some subtle things in the config that need to be set properly in order for it to work right. Here is an example config for your to look at.

{
"$schema": "https://mobilebuildtools.com/schemas/v2/buildtools.schema.json",
"appSettings": {
"YourProjectName": [
{
"accessibility": "Internal",
"className": "TheActualClassToUseToReferenceHere",
"delimiter": ";",
"namespace": "ThisIsTheNameSpaceButAlsoNeedsToExistAsAFolderInYourProjectInamedMineHelpers",
"rootNamespace": "AppsRootNamesSpaceIEMyCoolApp",
"properties": [ //*PUT YOUR SECRETS IN THIS SECTION WITH NAME/TYPE PAIRING LIKE BELOW. PS REMOVE THIS TEXT OR YOU WILL HAVE ERRORS*//
{
"name": "ApiKey",
"type": "String"
},
{
"name": "FunctionUri",
"type": "String"
},
{
"name": "EndPoint",
"type": "String"
}
]
}
]
},
"appConfig": {
"strategy": "TransformOnly"
},
"artifactCopy": {
"disable": false
},
"automaticVersioning": {
"behavior": "Off",
"environment": "All",
"versionOffset": 0
},
"css": {
"minify": false,
"bundleScss": false
},
"images": {
"directories": [],
"conditionalDirectories": {
"Debug": [],
"!Debug": [],
"iOS": [],
"Android": []
}
},
"manifests": {
"token": "$",
"variablePrefix": "Manifest_",
"missingTokensAsErrors": false,
"disable": false
},
"releaseNotes": {
"maxDays": 7,
"maxCommit": 10,
"characterLimit": 250,
"filename": "ReleaseNotes.txt",
"createInRoot": false,
"disable": false
},
"environment": {
"defaults": {},
"configuration": {
"Debug": {}
}
},
"debug": true
}
view raw buildtools.json hosted with ❤ by GitHub

So in the JSON file the basics I commented on are to set the project name, class name (I made a folder called Helpers and put “Helpers” there in that spot), and root namespace of the app. Then you can enter in your secret NAME/TYPE pairs, so it can be a string or whatever. Generally, it will be strings for your secrets but what you name them here is a reference in the actual secrets file itself.

The secrets file should be named after the class name you defined in your JSON file. So if you called it AppSecrets then you would name your secrets file “appsecrets.json.” Pretty straightforward forward but it can lead to problems later on that are hard to figure out without some debugging. In your secrets file you use the NAMES defined in your config as KEY/VALUE pairs in it and it is formatted in ordinary JSON format like below.

{
"ApiKey": "YOURAPIKEYHERE",
"EndPoint": "https://someendpoint.com",
"FunctionUri": "https://afunction.url"
}

Now in code, you refer to your secrets by the Class Name then a dot then the Secret Name you input into your config. So you would refer to ApiKey as “AppSecrets.ApiKey.” So in your code, you can refer to it like this, “var myapikey = AppSecrets.ApiKey.”

The rest can be ignored if you are not using the full capabilities of Mobile.BuildTools.

If you run into a compile error complaining about build tools that refer to some weird message about build properties, here is what you need.

<Project>
<Target Name="MBTHack"
BeforeTargets="Secrets"
DependsOnTargets="MobileBuildToolsInit">
</Target>
</Project>

Name it like in the gist and then place that file with your .sln file in the root of your project so MS Build can find it. Then the error should go away, I don’t remember the exact specifics of it but the file remedies that.

Adding A Foreground Service To Your .NET MAUI Android App – Updated Feb 14, 2023

It’s not well documented and I had to scrape stuff together from several sources and post on a couple of different forums but I have a working foreground service that puts up a notification in the notification tray that is tappable to reopen the app after you close it. Here is the code to enable it by file in your project:

using Android.App;
using Android.Content;
using Android.OS;
using AndroidX.Core.App;
namespace YourMAUIApp;
[Service]
public partial class MyForeGroundService : Service, IService
{
public const string NOTIFICATION_CHANNEL_ID = "10276";
private const int NOTIFICATION_ID = 10923;
private const string NOTIFICATION_CHANNEL_NAME = "notification";
private void StartForegroundService()
{
var intent = new Intent(Android.App.Application.Context, typeof(MainActivity));
var pendingIntentFlags = Build.VERSION.SdkInt >= BuildVersionCodes.S
? PendingIntentFlags.UpdateCurrent |
PendingIntentFlags.Mutable
: PendingIntentFlags.UpdateCurrent;
var pendingIntent = PendingIntent.GetActivity(Android.App.Application.Context, 0, intent, pendingIntentFlags);
var notifcationManager = GetSystemService(NotificationService) as NotificationManager;
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
CreateNotificationChannel(notifcationManager);
}
var notification = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
notification.SetContentIntent(pendingIntent);
notification.SetAutoCancel(false);
notification.SetOngoing(true);
notification.SetSmallIcon(Build.VERSION.SdkInt >= BuildVersionCodes.Tiramisu ? Resource.Drawable.ic_notification : Resource.Mipmap.appicon);
notification.SetContentTitle("My Aoo");
notification.SetContentText("My App Service is running");
StartForeground(NOTIFICATION_ID, notification.Build());
}
private static void CreateNotificationChannel(NotificationManager notificationMnaManager)
{
var channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME,
NotificationImportance.Low);
notificationMnaManager.CreateNotificationChannel(channel);
}
public override IBinder OnBind(Intent intent)
{
return null;
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
StartForegroundService();
return StartCommandResult.Sticky;
}
public void Start()
{
var intent = new Intent(Android.App.Application.Context, typeof(MyForeGroundService));
Android.App.Application.Context.StartForegroundService(intent);
}
public void Stop()
{
var intent = new Intent(Android.App.Application.Context, typeof(MyForeGroundService));
Android.App.Application.Context.StopService(intent);
}
}
namespace YourMAUIApp;
public partial class HomePage : ContentPage
{
public readonly HomeViewModel ViewModel;
public IService Service { get; }
public HomePage(IService _service)
{
InitializeComponent();
ViewModel = new HomeViewModel();
Service = _service;
}
private void Button_OnClicked(object sender, EventArgs e)
{
Service.Start();
}
private void StopButton_OnClicked(object sender, EventArgs e)
{
Service.Stop();
}
}
namespace YourMAUIApp;
public interface IService
{
void Start();
void Stop();
}
view raw IService.cs hosted with ❤ by GitHub
namespace YourMAUIApp;
public static class MauiProgram
{
public static IServiceProvider Services { get; private set; }
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder.Services.AddTransient<IService, MyForeGroundService>();
builder.Services.AddTransient<HomePage>();
builder
.UseMauiApp<App>()
.UseMauiCommunityToolkit()
.UseMauiCommunityToolkitCore()
.UseMauiCommunityToolkitMarkup()
.ConfigureFonts(fonts =>
{
fonts.AddFont("Roboto-Regular.ttf", "RobotoRegular");
})
var app = builder.Build();
Services = app.Services;
return app;
}
}
view raw MauiProgram.cs hosted with ❤ by GitHub

They are out of order for some reason but first, you want to create the interface in the root of your project called IService.cs with two methods Start and Stop. Just copy the example and adjust the namespace. After that is done, in your android folder create the foreground class, name it what you want but use the inherited interface and Service class. Once that is done, edit MauiProgram.cs to add the entries I have in the example for the service, the property, and the two builder services, and then end as I have it where it calls those services and then calls app. On your home page make a property referencing the service and then also a reference to them in the constructor as well to initialize the service.

At this point, you can either call it through a button or have it launch automatically however you want it from that page or whichever page you choose.

Now I am assuming you are only targeting Android in your project, if you are not then your need to create dummy classes in your other project folders that reference the IService interface so that there are no issues and then in whichever page you choose to launch the service from use:

#if ANDROID #ENDIF around the Service.Start()/Service.Stop() to isolate to just Android or if you were smart and blackhole the interface references in your other classes’ implementations then don’t worry about it 🙂

John

Edit!

You need one more thing if you’re targeting Android 13 and up. That would be the Post Notification permission and getting that from the user. Currently .NET MAUI essentials doesn’t have that built in but if you dig into the docs on Microsoft you’ll find out how to create an extension class to add it. Also, in your AndroidManifest.xml you need to add the following:

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

Then just do like normal before starting the service, check for the notification permission and request it if it’s not granted.

Edit 2!

If you’re building a Shell App and you see a crash when bringing the app off the back stack then here is the work around!

In your MainActivity.cs add Launchmode = Launchmode.SingleTop where I have it in the example below and it should go away.

using Android.App;
using Android.Content.PM;
namespace YourApp.Platforms.Android;
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density, LaunchMode = LaunchMode.SingleTop)]
public class MainActivity : MauiAppCompatActivity
{
}
view raw MainActivity.cs hosted with ❤ by GitHub

Edit 3!

Found this this morning during debugging! In your AndroidManifest.xml in the Application section add the following entry.

android:enableOnBackInvokedCallback=”true

John

[wpedon id=3183]

Apples New UIDevice.Name Entitlement

If you were like me and trying to figure out how to implement the new entitlement to get the iOS and iPadOS Device Name Entitlement to work then look no further!

First after you get your entitlement approval, go to the developers portal and go to your apps Identification entry and a new tab for entitlements will have showed up. There you will find the UIDevice.Name entitlement. Check it and save it. Then go to your profile for development and deployment and just save them again to ensure the new entitlement are attached with the ID is secured to the profiles. I’m not sure if you need a new development and deployment certs but I would revoke the old ones and just make a new set to be sure.

Once that is done, go into the key chain on your Mac and delete the old certs and install the new certs. Export P12’s and import them into your Visual Studio IDE (I would clean out the old certs first under %APPDATA%/Local/Xamarin/iOS) so that is has them as well on the Windows side and reimport the profiles from the developer portal. I would reimport the profiles into XCode and also VS Mac as well.

Once that is done, on your Mac/Windows machine edit your Entitlements.Plist and add the following line to it:

<key>com.apple.developer.device-information.user-assigned-device-name</key> <true/>

Do a clean and you should be able to do a build and see the device name now if all went well. I went through so many iterations of trying things and not finding information on the internet for doing it through MAUI that I hope that I have guided you in the right direction!

John

Is .NET MAUI ready now?

The short answer is maybe and the long answer is no. I started my next project totally Xamarin but when the news hit that although they were not sunsetting it until the end of 2023, the last big update to Xamarin.iOS was the last.

So it quickly turned into a .NET MAUI project and the conversion process is not a “day long” event like Microsoft put in their blog. It was more like a month and spending 1700 bucks on new MAUI controls. So, no Microsoft it’s not a day to convert.

Speaking of controls Telerik needs to lower their price because what you’re getting is in beta at best.

App Center support is alpha at best and not all features implemented. And don’t even think of targeting .NET 7 either as they only started working on supporting 6.

So my summary is they pushed .NET MAUI as fast as they could leaving all the support entities behind. I mean really it’s like the control and other providers are playing catch-up and .NET MAUI just plows on leaving what makes an app complete in the dust.

John

After thought for me is AppCenter is a big mess and barely supporting. NET 6. They are never going to catch up with .NET MAUI. Crashes is weird and Analytics is throwing an exception whenever called. I’ve submitted bug reports on them, hopefully they’ll get fixed.

Looking ahead!

Azure SSM is nearly complete, just lacking queue support. I plan on doing that in December as there doesn’t seem to be much to it. Also, I’ll be converting it to MAUI since they have really killed Xamarin for good.

In the mean time I have been busy raising funds and working on my next big project. Is gonna be really nice I think.

John

File Shares Are Done

The SDK is not the best to code against but they’re in the app now and it’s two thirds complete with the finish line coming in December with the final storage component to add.

I’ll be releasing it this week once I get directions and media done for the Share support. So be on the lookout for an update soon.

It will be important with File Shares to read the documentation as nested directories cause certain issues to arise and very specific procedures for dealing with moving and deleting them.

John