CISA Releases Analysis Reports on New FiveHands Ransomware

This article is contributed. See the original author and article here.

CISA is aware of a recent, successful cyberattack against an organization using a new ransomware variant, known as FiveHands, that has been used to successfully conduct a cyberattack against an organization.  

CISA has released AR21-126A: FiveHands Ransomware and MAR-10324784-1.v1: FiveHands Ransomware to provide analysis of the threat actor’s tactics, techniques, and procedures as well as indicators of compromise (IOCs).  These reports also provide CISA’s recommended mitigations for strengthening networks to protect against, detect, and respond to potential FiveHands ransomware attacks.

CISA encourages organizations to review AR21-126A and MAR-10324784.r1.v1 for more information.

Introducing React Video Banner Web Part

Introducing React Video Banner Web Part

This article is contributed. See the original author and article here.

In this post, we will see how easy it is to build a cool looking video banner web part using SPFx with the help of PnP reusable property pane controls. First of all, the requirements: 



  • The web part should look like a banner on top of pages, with a video playing

  • Ability to change the overlay text on this video

  • Control the banner area size


This is what the PnP React Video Banner web part offers, once you add the web part to your page, you will be able to select a video (using the file picker control from the PnP Reusable Property Pane Controls), you will be able to modify the text overlay and its color, control the height of the video area and lastly (at least for now) modify the brightness: 


 


  derhallim_0-1620249069072.png


 


 These settings would provide you with a web part that looks like this: 


 


 derhallim_4-1620249695924.png


 


 


Now let’s have a look at the code itself which is pretty simple. The file structure can be seen below:


 


                                                                


 derhallim_1-1620252146944.png


 


 


The web part has only one functional component named: VideoBackground that accepts the following properties as defined in the IVideoBackgroundProps.ts file: wpTitle (string), videoUrl (string), labelColor (string), brightness (number), height (number).


 


 derhallim_2-1620252225550.png


 


The video url and the label color are set with the help of PnP Property Pane Controls as shown below: 


 


 derhallim_0-1620252048668.png


 

 


Once the properties are setup on the VideoBackgroundWebPart.ts file, we pass them to the VideoBackground.tsx component. 


 



 derhallim_6-1620252844193.png

 



 

All good so far? Now in our functional component, we have an HTML video control where the source of the video is set to the videoUrl prop we pass and we play with the CSS filter prop to set the brightness by adding the value concatenated with % as we need a brightness percentage: 

 

 derhallim_3-1620252272134.png

 





 




 


Notice the ref attribute on the video control? The reason we have it is that we want to refresh the video whenever we change the video url. By default, when changing the properties, all values will be reflected except for the video url, it needs to be explicitly refreshed on the video control. So we get a reference to the video control using React’s ref, where we define the “vRef” value on the functional component itself. 


 


We then use React’s useEffect to check if the video url has changed or not, if it has changed, we call the load() function on the video reference itself: 


 



 derhallim_4-1620252332115.png

 



 

Some notable points about the CSS used is the div that’s available just before the video control, it’s aligned using an absolute position with a display of flex to position the h1 element inside of it. The video element itself has a CSS property object-fit: cover.

 

As demonstrated, with SPFx and the help of PnP Reusable Property Pane controls, building web parts using modern development techniques is very easy and isn’t time consuming as some may think! Source code is available on Github along with other awesome web parts by the community, for more information about all the PnP offerings, checkout https://aka.ms/m365pnp 

#SharingIsCaring

 

 


 

Using Power Automate And Graph API To Manage External Access To Teams

Using Power Automate And Graph API To Manage External Access To Teams

This article is contributed. See the original author and article here.

Matt Collins Jones and I presented API’s – The most powerful tool, anyone can use! for D365 UG and Swiss Power Saturday recently and I thought it would be good to share the Cloud Flow I created to automate the onboarding of external users to a Microsoft Team.


This is usually an admin driven activity – A team owner will have to type in the email address for each guest they want to add, rather than something you can push to external users and allow them to request access.


By using the Graph API via a Custom Connector, Microsoft Forms and Power Automate, we are able to realise this quickly and save a lot of time and effort in the manual process.


Also, I have been lucky to have this solution accepted as part of the samples in the Microsoft Patterns And Practices initiative, so the Flow, Custom Connector and implementation instructions are available in GitHub here.


Getting Hands-On With Graph


The main part of this flow is numerous calls to the Graph API. The Graph API is Microsoft’s standard endpoint to expose and interact with data relevant to your tenant. It includes Microsoft 365 (such as Teams, Exchange, SharePoint, Workspace Analytics), Enterprise and Mobility and even Windows 10 activities and devices. It really should be seen as a single stop shop for anything and everything in your tenant. The only thing it doesn’t expose is D365 data.


 


There is a Graph connector already available in Power Automate, but it is very limited to Security considerations. Thankfully, the rest of the Graph API abilities are available, but you have to go via a custom connector. You could call these directly via an HTTP request action, but by wrapping the Graph API in a connector, you are enabling other members of your organisation to re-use the connector and security you establish.


 


Microsoft also allows you to “play” with the Graph API as well, via the Graph Explorer. This web interface shows you all the sample calls you can make and also what permissions you require to call it and allows you to set up a call without using Power Automate or configuring a connector. It really should be the starting point for any Graph Customer Connector.



LinkeD365_0-1620296690001.png

 




If things go wrong, it is usually around the permissions. Within the Graph Explorer you can consent to these extra permissions on the fly, but more importantly, tells you what you need to configure in the permissions of your App registration to allow your connector the same access.



LinkeD365_1-1620296689997.png

 


Granting Permissions


Now that we understand what permissions that are needed to get at the actions required, let’s jump in and create an Azure App Registration. This allows you to grant rights to a particular application, which presents a client secret and App ID as part of the request. By doing this registration, you establish trust between your app (Custom Connector in our case) and your tenant.


 


Navigate to https://aad.portal.azure.com and log in. Select Azure Active Directory then App registrations. Select New, give it an appropriate name then hit Register.


 


In the next screen, record the Application Id, going to need it later. On the left, select Certificates & secrets



LinkeD365_2-1620296727206.png

 




Select New client secret give it a name & expiry date and select Save.



LinkeD365_3-1620296726932.png

 




Ensure you copy the Value here, you will only be able to see this for a short while, if you navigate away it will be gone. Not a big deal, just recreate the client secret, but you will need it later. Now select API permissions. This will list what permissions this registration has, and by inference, the caller using the client secret/application id.


 


Select the Add a permission button.



LinkeD365_4-1620296727532.png

 




This presents a choice of which API to expose. The first on the list is Microsoft Graph, the one we want.



LinkeD365_5-1620296727260.png

 




Select Delegated Permissions (Custom connectors doesn’t support Application permissions yet, will run in the context of the person who runs the flow, so use an admin/system account) then type in the permission you want, listed here.



  • Directory.ReadWrite.All

  • User.Invite.All

  • User.ReadWrite.All



LinkeD365_6-1620296727107.png

 




Select Add Permissions to return you to the Configured permissions screen, then select Grant Admin consent button. This shortcuts and pre-approves the app.


 


Leave this tab open and let’s go and define our custom connector.


 


Defining The Custom Connector


Jan Bakker has done an excellent job of walking you through this, here. His article goes into a lot of detail, so I will just take you through what is needed for this project.


 


In make.powerapps.com, select the appropriate environment and chose Custom Connectors under Data. Then select New custom connector. You can import from various sources, but we want to create from blank, give it a name then fill out the next page.



LinkeD365_7-1620296727214.png

 




On the next screen, there are four tabs, which we need to step through. First the General Tab.



LinkeD365_8-1620296727082.png

 




Other stuff is nice to have and you should document your work. Ensure Scheme is HTTPS and Host/Base URL are populated.



  • Host – graph.microsoft.com

  • Base URL – /v1.0


Select the Security Tab next, Authentication type is OAuth 2.0. You should be presented with the below screen.



LinkeD365_9-1620296727183.png

 




Now, this is where we need to use the values you saved (you did save them?) when you were registering your app up here. Client Id is populated with the Application (client) ID, the Client secret is populated with the Value from the Client Secret grid. Login URL will be populated for you. The Resource URL value should be https://graph.microsoft.com.Select Create Connector now, as you need the Redirect URL, created when you create the connector to put back into your App registration to complete the security process.


 



LinkeD365_10-1620296727075.png

 




I think that this is now standard, but just in case, copy the Redirect URL and go back to your App Registration in Azure AD. Click on the link highlighted.



LinkeD365_11-1620296727170.png

 




Select Add a platform then chose Web. Enter the Redirect URL from the Custom Connector. Now we are ready to define the actions for our connector.


Creating the Actions


For our flow, we need 3 actions, Get the owners of a team, Get a user and Invite a User. This is where Graph Explorer and Postman help. You need to establish what you are sending and what you expect back for each action. For example, lets walk through the Get Owners of a team.


 


Select New Action and Populate General section. The Operation ID needs to be unique and is what appears within Power Automate when you select it.



LinkeD365_12-1620296727067.png

 




I usually use the same for each, but be creative and descriptive. Select Import from sample then use the url below as the URL and select Get as the Verb.


 


URL – https://graph.microsoft.com/v1.0/groups/{teamId}/owners



LinkeD365_13-1620296727114.png

 




By placing teamid in curly brackets { } you denote to the custom connector you want to use a parameter in that URL. You can call https://graph.microsoft.com/v1.0/groups/{teamId} (without the /owners) but that will return the detail from the group. In this I want get associated data, hence the /owners.


 


Select Import. You are returned to the definition screen, where we can see that the request has been populated for us.



LinkeD365_14-1620296727100.png

 




We are ready to test our Get Owners now. Update the connector once more then head over to the Test tab. You will have to create a connection if not already done, which prompts you to establish who you are running the connector under (only for testing). Then supply a team id. These can be found by using Graph Explorer to find all teams. Hit the Test operation and if everything is working you will get a 200 response with some JSON in a body showing you all the information about the owners.



LinkeD365_15-1620296727218.png

 




To just define the others


Get User


Verb: Get, URL: https://graph.microsoft.com/v1.0/users?$filter=


Invite User


Verb: Put, URL: https://graph.microsoft.com/v1.0/invitations, Body is below, as you need to define a new invite, with the required parameters. The data doesn’t matter, just the parameters that you need to pass.

{
    "invitedUserEmailAddress": "emailaddress",
    "inviteRedirectUrl": "https://myapp.contoso.com",
    "invitedUserDisplayName": "Testy McTest",
    "sendInvitationMessage": true
}

Make sure you test all your actions and lets move on to the Form.


Microsoft Form To Capture Information


Not going to dwell here, as others are doing a much better job at describing Forms. Basically, a simple form to define First and Last name, the email address and a choice field to define which team the user wants access to.



LinkeD365_16-1620296727638.png

 




The teams list will have to be maintained to those that you want the public to be able to request access to.


 


Finally, lets take a look at the flow.


Power Automate Definition


This Flow is triggered by a new response being submitted against the Form defined above. Next, get the response details.



LinkeD365_17-1620296727108.png

 




Next, retrieve all the Teams in your environment. This will return a JSON object which defines an array of Team definitions. We need to filter that to the one the user selected so that we can get the team id.



LinkeD365_18-1620296726929.png

 




To do this, I use the Filter Array action, pass in the output from the List Teams and ensure we select where team Name is equal to the team selected (the Which Team? field in my case).



LinkeD365_19-1620296726827.png

 




Next, is a compose statement. I do that just to simplify the way the flow works, as the return of filter array is an array, and I just want the first one.



LinkeD365_20-1620296726837.png

 



body('Filter_array')[0]?['id']

Next, lets get the Owners of the team selected, using the Id just retrieved. This is the first time using the Custom Connector, it is available under the Custom Tab.



LinkeD365_21-1620296726920.png

 




Selecting the connector will show the actions or triggers available.



LinkeD365_22-1620296726951.png

 




The parameters are those that were defined in the Custom connector, passing in the output from the compose above.



LinkeD365_23-1620296726812.png

 




Now, the response back from Get Owners is a JSON object, so next, Parse the JSON so there is a list of JSON objects for the flow to use. All that is needed in the approval that comes next is the email address(es) of the return from the owners call. But the approval needs a semi-colon separated list of emails. To achieve this, firstly use a Select to just return the email address from the JSON object, then join the output to that with a semi colon.



LinkeD365_24-1620296727149.png

 




Next, start an approval. This is populated to let the owner know who has asked for access to the team and which team.



LinkeD365_25-1620296726984.png

 




Check whether the response is positive. If this was for production, I would probably send an email to the requesting user to let them know that they were denied access. You could also use the response written in the rejection.



LinkeD365_26-1620296726933.png

 




In the Yes path, call the Custom connector again to check if the user is already a part of your organisation as a guest user. As the parameter is expecting a query, use the expression below



LinkeD365_27-1620296726901.png

 




mail eq ‘Email Parameter from the Form response’

mail eq 'Email Parameter from the Form response'

 


Next, check the length of the returned object from the custom connector. This basically checks if the user already belongs to your environment.



LinkeD365_28-1620296726899.png

 




length(outputs(‘GetUser’)?[‘body/value’])

 


If there is a value in the return, use the return to invite the user to the team.



LinkeD365_29-1620296726913.png

 




The User id is returned by using the expression below

body('GetUser')?['value'][0]?['id']

 


On the negative side, firstly invite the user to your organisation by using the final action of the custom connector.



LinkeD365_30-1620296727013.png

 




And finally, use the response from your custom connector, the invited user to the team.



LinkeD365_31-1620296727008.png

 




That’s it! There is a lot of configuration here, but you can see how you can extend your usage of Power Automate to automate a function usually confined to manual work by the team owner.

This post was originally published on LinkeD365.blog



Simple reminders for any Teams Channel or Chat message

Simple reminders for any Teams Channel or Chat message

This article is contributed. See the original author and article here.

Forgetting to take action on a message, or where that message was?Forgetting to take action on a message, or where that message was?


For busy people who have their lives invested in Microsoft Teams, whether collaborating with colleagues in Team Channels or using the Chat functionality, it’s easy to forget:



  • To take action or reply to a message

  • The location of where that message is! Is it in a Chat, or a Team Channel? How far up do I have to scroll?


Outlook’s solution: a well trodden path for many


Flags in Outlook have been the bridge to emails and task managementFlags in Outlook have been the bridge to emails and task management


 


 


In Outlook, there are “flags” which can be set to remind yourself to take action for a particular email.


 


However, this functionality is missing from Teams. Even if you are a well seasoned ToDo and Planner user, you would still have to use the Copy Link feature and paste that into the ToDo/Planner task, which can be quite tedious. 


Copy link to a Teams Channel messageCopy link to a Teams Channel message


Plus I entering a phase where I was forgetting that I had to respond to messages. Sometimes I ended up talking to Google (I use an Android phone, so you might be talking to Siri) to remind myself, but that still doesn’t take you straight back to the original message with a single click – you still had to do a lot of navigation before you arrived at the message you were supposed to take action on.


 


My poor colleagues were also getting flooded with Teams messages. If they were diligent and cleared their activity bell notifications, they would potentially lose track of a visual reminder that they need to prompt them to action on a message.




So what if you just needed a simple and effective visual reminder, either at some hours/minutes down the track or at a specific time?




A Flow, some delay, and four Adaptive Cards


In comes Power Automate with a few adaptive cards to the rescue – this flow will generate a reminder via the Flow bot at a certain number of hours/minutes, or at a specified time to remind you to take action for a message!


The reminder card we wish to send ourselvesThe reminder card we wish to send ourselves


 


The beauty of this Flow is that it will give you one-click access back to the conversation thread within the team, or back to the chat with a person or a group of people. 


 


So in the blog post below, the Flow will be explained in greater detail, and some caveats highlighted for anyone wanting to pursue this quick reminder flow!


 




Note: this was partially inspired by Microsoft’s own template that you can create directly from Power Automate, but extends it to bring more flexibility to the reminder time, and also bring a far more visual experience via adaptive cards rather than just the Flow bot.




Inspired by Microsoft


When I first saw the template provided by Microsoft, I thought: this is nice, but it’s a bit too elementary with the fixed timeframes from the choice radio buttons:


 


Microsoft's own sample FlowMicrosoft’s own sample Flow


 


...is perhaps a bit too restrictive…is perhaps a bit too restrictive


 


However, that was definitely a starting point. The sample Flow used an adaptive card (with some Input.Choice options) and a Delay action. Why not take this further?


Ingredients


Here’s the “ingredients” needed for the flow to allow ourselves to set a reminder at a particular hour/minute offset from now OR at a specific time:



  1. One to get user input regarding when they’d like to be reminded

    The reminder setting card can accept an hour/minute offset or absolute time as inputThe reminder setting card can accept an hour/minute offset or absolute time as input



  2. One for the reminder itself:

    The reminder card itself, with links to the original message and chat with message authorThe reminder card itself, with links to the original message and chat with message author



  3. Two other cards which are for catching errors:
    Cards reminding users of input errorCards reminding users of input error


The Flow


1. Data entry card


So the concept is basically taken from what Microsoft provided, but here we extend the adaptive card by using an Action.ToggleVisibility button to show and hide parts of a card: the relative time entry and the absolute time entry containers, in blue and green respectively:


The reminder setting card, with an initially invisible containerThe reminder setting card, with an initially invisible container


 


The Change reminder type button within the gray container is Action.ToggleVisibility button that you can add from the card elements bar on the left of the adaptive card designer screen. The JSON code looks like this:


Action Toggle Visibility.png


 


The action button targets the section-hours (blue) and section-absolute-time (green) containers – i.e. when pressed, turns the visibility of section-hours off and section-absolute-time (as the respective ids of the containers) on, and vice versa. The blue and green containers are never on at the same time.


 


The ID and initial visibility of the blue containerThe ID and initial visibility of the blue container


 For the Change reminder type button to turn the blue and green containers on and off, the Initially visible checkbox must be



  • Checked for the blue container

  • Unchecked for the green container:


The green container should initially be invisibleThe green container should initially be invisible


Within the containers are also ColumnSets to house the fields side by side, just to make it look nice.


Use the ColumnSet to place fields and labels (as TextBlock) adjacent to each otherUse the ColumnSet to place fields and labels (as TextBlock) adjacent to each other


 The fields also need TextBlocks above them as their labels (until we get Adaptive Cards v1.3 in Teams), as well as having some of the parameters set properly:


Set some restrictions on the fields, and place TextBlocks above them as labelsSet some restrictions on the fields, and place TextBlocks above them as labels


Finally, the orange container just contains what to remind yourself of, and has an Input.ChoiceSet to provide the dropdown menu:


Input.ChoiceSet for dropdown menuInput.ChoiceSet for dropdown menu


 


Below is the complete JSON code for the adaptive card that captures the user input:


 


 


 


 


 


 


 

{
    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
    "type": "AdaptiveCard",
    "version": "1.2",
    "body": [
        {
            "type": "Container",
            "bleed": true,
            "style": "warning",
            "items": [
                {
                    "type": "ColumnSet",
                    "columns": [
                        {
                            "width": "75px",
                            "type": "Column",
                            "items": [
                                {
                                    "type": "Image",
                                    "url": "https://normanhurb-h.schools.nsw.gov.au/content/dam/doe/sws/schools/n/normanhurb-h/icons/schedule.png"
                                }
                            ]
                        },
                        {
                            "width": "stretch",
                            "type": "Column",
                            "items": [
                                {
                                    "type": "TextBlock",
                                    "weight": "Bolder",
                                    "size": "Large",
                                    "text": "**Set myself a reminder about this message**",
                                    "color": "Attention",
                                    "fontType": "Default",
                                    "wrap": true
                                }
                            ],
                            "verticalContentAlignment": "Center"
                        }
                    ]
                }
            ]
        },
        {
            "type": "TextBlock",
            "isSubtle": true,
            "wrap": true,
            "text": "Fill out this card in entirety, and you'll be reminded by the Flow bot after the time selected."
        },
        {
            "type": "Container",
            "separator": true,
            "style": "emphasis",
            "items": [
                {
                    "type": "ColumnSet",
                    "columns": [
                        {
                            "type": "Column",
                            "width": "auto",
                            "items": [
                                {
                                    "type": "ActionSet",
                                    "actions": [
                                        {
                                            "type": "Action.ToggleVisibility",
                                            "title": "Change reminder type",
                                            "targetElements": [
                                                "section-hours",
                                                "section-absolute-time"
                                            ]
                                        }
                                    ],
                                    "spacing": "None"
                                }
                            ],
                            "verticalContentAlignment": "Center"
                        },
                        {
                            "type": "Column",
                            "width": "stretch",
                            "items": [
                                {
                                    "type": "TextBlock",
                                    "text": "Click on Change reminder type to select whether to remind myself at a specific time, or after a certain number of hours from now.",
                                    "wrap": true,
                                    "color": "Accent",
                                    "weight": "Bolder"
                                }
                            ],
                            "verticalContentAlignment": "Center"
                        }
                    ]
                }
            ]
        },
        {
            "type": "Container",
            "style": "accent",
            "items": [
                {
                    "type": "TextBlock",
                    "wrap": true,
                    "color": "Accent",
                    "weight": "Bolder",
                    "text": "Remind myself after"
                },
                {
                    "type": "ColumnSet",
                    "columns": [
                        {
                            "type": "Column",
                            "width": "stretch",
                            "items": [
                                {
                                    "type": "TextBlock",
                                    "text": "Hours",
                                    "wrap": true,
                                    "maxLines": 0,
                                    "spacing": "None",
                                    "isSubtle": true,
                                    "size": "Small"
                                },
                                {
                                    "type": "Input.Number",
                                    "placeholder": "Type in the delay in hours",
                                    "id": "remind-hours-later",
                                    "spacing": "None",
                                    "min": 0,
                                    "max": 670
                                }
                            ]
                        },
                        {
                            "type": "Column",
                            "width": "stretch",
                            "items": [
                                {
                                    "type": "TextBlock",
                                    "text": "Minutes",
                                    "wrap": true,
                                    "size": "Small"
                                },
                                {
                                    "type": "Input.Number",
                                    "placeholder": "Type in the delay in minutes",
                                    "spacing": "None",
                                    "min": 1,
                                    "max": 59,
                                    "id": "remind-minutes-later"
                                }
                            ]
                        }
                    ]
                },
                {
                    "type": "TextBlock",
                    "wrap": true,
                    "text": "Hours and minutes can contain decimals, e.g. **1.2 hours = 1 hour 12 minutes**",
                    "spacing": "None",
                    "size": "Small"
                }
            ],
            "id": "section-hours"
        },
        {
            "type": "Container",
            "style": "good",
            "items": [
                {
                    "type": "TextBlock",
                    "wrap": true,
                    "color": "Accent",
                    "weight": "Bolder",
                    "text": "Remind myself at this time"
                },
                {
                    "type": "ColumnSet",
                    "columns": [
                        {
                            "type": "Column",
                            "width": "stretch",
                            "items": [
                                {
                                    "type": "TextBlock",
                                    "text": "Date",
                                    "wrap": true,
                                    "maxLines": 0,
                                    "spacing": "None",
                                    "isSubtle": true,
                                    "size": "Small"
                                },
                                {
                                    "type": "Input.Date",
                                    "id": "remind-date",
                                    "spacing": "None"
                                }
                            ]
                        },
                        {
                            "type": "Column",
                            "width": "stretch",
                            "items": [
                                {
                                    "type": "TextBlock",
                                    "text": "Time",
                                    "wrap": true,
                                    "maxLines": 0,
                                    "spacing": "None",
                                    "isSubtle": true,
                                    "size": "Small"
                                },
                                {
                                    "type": "Input.Time",
                                    "id": "remind-time",
                                    "spacing": "None"
                                }
                            ]
                        }
                    ]
                },
                {
                    "type": "TextBlock",
                    "text": "Ensure that n- Both **Date** and **Time** are selectedn- Date and time are no later than 30 days of the current time",
                    "wrap": true,
                    "size": "Small",
                    "spacing": "None"
                }
            ],
            "id": "section-absolute-time",
            "isVisible": false
        },
        {
            "type": "Container",
            "style": "attention",
            "items": [
                {
                    "type": "TextBlock",
                    "wrap": true,
                    "color": "Accent",
                    "weight": "Bolder",
                    "text": "Remind myself to"
                },
                {
                    "type": "Input.ChoiceSet",
                    "choices": [
                        {
                            "title": "Reply to the message",
                            "value": "message-reply"
                        },
                        {
                            "title": "Get something done",
                            "value": "message-get-something-done"
                        }
                    ],
                    "placeholder": "Select the action to be reminded of",
                    "spacing": "None",
                    "id": "message-subsequent-action"
                }
            ]
        }
    ]
}

 


 


 


 


 


 


 


2. Reminder card groundwork


After some experimentation with the For a selected message trigger for Teams, it seems that there is a good amount of dynamic content that would be useful for the reminder card:


For a selected (Teams) message provides a lot of useful dynamic contentFor a selected (Teams) message provides a lot of useful dynamic content


 


We will return to this card after looking at the upcoming sections after having a look at the actions which the flow will take.


 


3. Variables required


Some variables are required to hold hold some of the data:


Some variables are required to hold the time informationSome variables are required to hold the time information


 


Then we get the user profiles of the message sender and the person who initiated the flow: interestingly, only the AAD ID is available as dynamic content from the trigger, but thankfully the Get user profile (V2) action is able to handle this and return all of the information required:


z3019494_1-1620122926624.png


4. Check for Chat or Channel conversation message and what action to take


We then build the Original message information block by testing whether the message came from a private chat, or from a Team channel with a simple check of whether the team dynamic content is null or not (input null as an expression, not dynamic content):


Check whether the message is in a Chat or Channel, and building the adaptive card to suit the occasionCheck whether the message is in a Chat or Channel, and building the adaptive card to suit the occasion


 


 



  • If the message is from a Team Channel, then the List channels action is run, and a filter applied so that only the Channel Name is extracted out of the channels of the team.

    • Channel Id is from the List channels action

    • Channel ID (note the case sensitivity!) is from the From a selected message action.



  • The JSON card blocks are then saved in the TeamChannelBrick variable.


 


The ActionToTake variable is also populated after checking for whether it’s been left blank, or one of the selections have been made:


Checking whether the ActionToTake choice has been set, and building the adaptive card brick to suit the inputChecking whether the ActionToTake choice has been set, and building the adaptive card brick to suit the input


 


 


5. Time calculations, data types & error handling 


The difficult part is this bit: making sure the user’s inputs for hours/minutes, or absolute time is valid!


 


We quickly check whether either date or time entered is null or not, and if so, the user probably has inputted the hour/minute offset instead since that is the default:


Checking to see whether absolute or relative time delay has been inputtedChecking to see whether absolute or relative time delay has been inputted


 


 


 


 


In the case where the user enters the hours/minutes offset to be reminded:



  • Check whether the Hours entered is blank or not (note that there’s a very subtle difference between blank and null!). If so, set the HoursToDelay variable to a “0” or simply use the hours inputted.

  • Check whether the Minutes entered is blank or not. If so, set the MinutesToDelay variable to a “0” or simply use the hours inputted.


z3019494_1-1620123840984.png


Finally, the TotalTimeDelay is set to the following expression:


mul(add(mul(variables(‘HoursToDelay’),60),variables(‘MinutesToDelay’)),60)

e.g.



  1. multiply the number of hours by 60 to obtain the number of minutes

  2. add that to the number of minutes to delay by

  3. multiply the final result up by another 60 to obtain the number of seconds


In the case where the user specifies an absolute time to be reminded


A lot more string processing is required!


 



  1. Compose – date selected: compose the date/time that the user selected, into ISO8601 format. The caveat here: you need 7 decimal places after the seconds!

  2. Compose – ticks of date to delay until: find the number of ticks from the previous compose action:

    ticks(outputs(‘Compose_-_date_selected’))


  3. Convert time zone – to UTC+10 (where I live): change this to wherever you are in the world.

  4. Compose – ticks of current time: get the current time’s ticks

  5. Compose – difference in ticks: subtract the ticks of current time (4) from the ticks of the selected time (1).

  6. Then check for whether the selected date is before the current time by seeing whether (5) is a negative number of not in the Condition – check selected date isn’t on or before reminder date

  7. Then do some final checks for whether the number of seconds falls on “0” by

    1. Converting the ticks into minutes/seconds (Compose – ticks to seconds)

      The TotalTimeToDelay variable in this instance, should contain this expression:

      add(0,div(outputs(‘Compose_-_difference_in_ticks’),10000000))


    2. Checking whether there’s remnant seconds (by looking for modulo 60) in Compose – modulo seconds action. If the number of seconds to delay by, falls on “0” then just add 1 more second to it in case the user enters a time which is just less than 1 minute as the div formula will only work with integers. 

      The TotalTimeToDelay variable in this instance, becomes this expression instead:

      add(1,div(outputs(‘Compose_-_difference_in_ticks’),10000000))


      The reason for this check is that the Delay action, is very fussy. It only takes integers, and can’t cope with an input of (you’d think that an input of “0” into the Delay action would just cause it to continue full steam ahead instead of sitting there and waiting!)




Absolute time calculations: finding out the TotalTimeToDelayAbsolute time calculations: finding out the TotalTimeToDelay


 


One final major condition block: check to see if the user has set a date over 28 days (or 720 hours)


 


We check the TotalTimeToDelay variable and see how many days it has racked up:


div(int(variables(‘TotalTimeToDelay’)),86400)

This check is needed as Power Automate will time out after 30 days. But let’s just be a little more conservative and set that at 28 days, and throw an error if so. This will ensure no reminders (especially those over 30 days) are quietly dumped without the user’s knowledge.


Double checking that the user has entered a date no further than 28 days out to ensure the flow doesn't time outDouble checking that the user has entered a date no further than 28 days out to ensure the flow doesn’t time out


 


 


The adaptive card that reports the error if a user enters a date that is greater than 28 days:


 


 


 

{
    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
    "type": "AdaptiveCard",
    "version": "1.2",
    "body": [
        {
            "type": "Container",
            "bleed": true,
            "style": "warning",
            "items": [
                {
                    "type": "ColumnSet",
                    "columns": [
                        {
                            "width": "75px",
                            "type": "Column",
                            "items": [
                                {
                                    "type": "Image",
                                    "url": "https://normanhurb-h.schools.nsw.gov.au/content/dam/doe/sws/schools/n/normanhurb-h/icons/error.png"
                                }
                            ]
                        },
                        {
                            "width": "stretch",
                            "type": "Column",
                            "items": [
                                {
                                    "type": "TextBlock",
                                    "weight": "Bolder",
                                    "size": "Large",
                                    "text": "**Error in setting a reminder for Teams message**",
                                    "color": "Attention",
                                    "fontType": "Default",
                                    "wrap": true
                                },
                                {
                                    "type": "TextBlock",
                                    "text": "Reminder set for too far ahead!",
                                    "wrap": true,
                                    "size": "Large",
                                    "weight": "Bolder",
                                    "color": "Accent",
                                    "spacing": "None"
                                }
                            ],
                            "verticalContentAlignment": "Center"
                        }
                    ]
                }
            ]
        },
        {
            "type": "TextBlock",
            "isSubtle": true,
            "wrap": true,
            "text": "Oops. You've tried to set yourself a reminder for @{outputs('Compose_-_check_for_28_day_limit')} days later! Please ensure you set it for less than 28 days.nnIf you need something more sophisticated, use **Microsoft To Do** or **Microsoft Planner**."
        },
        {
            "type": "TextBlock",
            "text": "Original message information",
            "wrap": true,
            "separator": true,
            "size": "Small",
            "color": "Accent"
        },
        {
            "type": "FactSet",
            "facts": [
                {
                    "title": "Message author",
                    "value": "@{outputs('Get_user_profile_(V2)_-_person_who_typed_the_message')?['body/displayName']}"
                }
            ],
            "spacing": "None"
        },
        {
            "type": "TextBlock",
            "text": "Original message",
            "wrap": true,
            "separator": true,
            "color": "Accent",
            "size": "Small"
        },
        {
            "type": "TextBlock",
            "text": "@{triggerBody()?['entity']?['teamsFlowRunContext']?['messagePayload']?['body']?['plainText']}",
            "wrap": true,
            "spacing": "None"
        },
        {
            "type": "Container",
            "separator": true,
            "style": "emphasis",
            "items": [
                {
                    "type": "ColumnSet",
                    "columns": [
                        {
                            "type": "Column",
                            "width": "50px",
                            "items": [
                                {
                                    "type": "Image",
                                    "url": "https://normanhurb-h.schools.nsw.gov.au/content/dam/doe/sws/schools/n/normanhurb-h/icons/alert.png"
                                }
                            ]
                        },
                        {
                            "type": "Column",
                            "width": "stretch",
                            "items": [
                                {
                                    "type": "TextBlock",
                                    "text": "Action that you were going to take",
                                    "wrap": true,
                                    "separator": true,
                                    "color": "Accent",
                                    "size": "Small"
                                },
                                {
                                    "type": "TextBlock",
                                    "wrap": true,
                                    "spacing": "None",
                                    "text": "@{variables('ActionToTake')}"
                                }
                            ],
                            "verticalContentAlignment": "Center"
                        }
                    ]
                }
            ]
        },
        {
            "type": "ActionSet",
            "actions": [
                {
                    "type": "Action.OpenUrl",
                    "title": "Go back to the message and set the reminder again",
                    "iconUrl": "https://normanhurb-h.schools.nsw.gov.au/content/dam/doe/sws/schools/n/normanhurb-h/icons/teams.png",
                    "url": "@{triggerBody()?['entity']?['teamsFlowRunContext']?['messagePayload']?['linkToMessage']}"
                }
            ]
        }
    ]
}

 


 


 


6. The Delay vs Delay Until action


Setting the delaySetting the delay


 


We are now ready to delay the flow!


 


Initially there was a consideration to use the Delay Until action if the user enters an absolute date/time, until a major stumbling block was encountered: time zones!


 


Power Automate basically works in UTC or UTC-8, whereas I live in UTC+10. Having said that, the documentation for the Delay Until action is quite scant, and it doesn’t seem to take into consideration what timezone you are in. Hence all of the effort to subtract ticks and calculate remnant seconds etc when the user selects the date/time option.


7. Oops – don’t forget the characters that adaptive cards dislike!


Two more Compose actions are required before we pop the reminder card out, namely:


z3019494_2-1620126836459.png


 


Unfortunately if you wanted to insert the Plain Text Message dynamic content into the replace formula, you’re almost out of luck. Here’s where Compose comes to the rescue. The Compose – PTM without quotes action has this in its formula:


 


replace(replace(outputs(‘Compose_-_Plain_Text_Message’),'” ‘,”),’ “‘,”)

which replaces every instance of spacedouble-quote and double-quotespace with empty strings, in order to not allow the reminder card to spit the dummy with any double quotation marks.


 


8. The reminder card’s code


With the TotalChannelBlock variable inserted into the appropriate location so that the correct information about the message is displayed to the user who initiated the flow:


 


z3019494_3-1620127059580.png


…and a summary at the bottom of the card (pop the Show advanced options open!) to ensure a summary is sent – especially useful if your smartwatch notifications rely on a summary of sorts:


 


z3019494_0-1620127122452.png


 


 


 


 

{
    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
    "type": "AdaptiveCard",
    "version": "1.2",
    "body": [
        {
            "type": "Container",
            "bleed": true,
            "style": "warning",
            "items": [
                {
                    "type": "ColumnSet",
                    "columns": [
                        {
                            "width": "75px",
                            "type": "Column",
                            "items": [
                                {
                                    "type": "Image",
                                    "url": "https://normanhurb-h.schools.nsw.gov.au/content/dam/doe/sws/schools/n/normanhurb-h/icons/schedule.png"
                                }
                            ]
                        },
                        {
                            "width": "stretch",
                            "type": "Column",
                            "items": [
                                {
                                    "type": "TextBlock",
                                    "weight": "Bolder",
                                    "size": "Large",
                                    "text": "**Reminder for Teams message**",
                                    "color": "Attention",
                                    "fontType": "Default",
                                    "wrap": true
                                }
                            ],
                            "verticalContentAlignment": "Center"
                        }
                    ]
                }
            ]
        },
        {
            "type": "TextBlock",
            "isSubtle": true,
            "wrap": true,
            "text": "This is a reminder message you set for yourself atn"
        },
        {
            "type": "TextBlock",
            "text": " **@{body('Convert_time_zone_-_time_executed')}**.",
            "wrap": true,
            "spacing": "None"
        },
        {
            "type": "TextBlock",
            "text": "Original message information",
            "wrap": true,
            "separator": true,
            "size": "Small",
            "color": "Accent"
        },
        {
            "type": "FactSet",
            "facts": [
@{variables('TeamChannelBrick')}
            ],
            "spacing": "None"
        },
        {
            "type": "TextBlock",
            "text": "Original message",
            "wrap": true,
            "separator": true,
            "color": "Accent",
            "size": "Small"
        },
        {
            "type": "TextBlock",
            "text": "@{outputs('Compose_-_PTM_without_quotes')}",
            "wrap": true,
            "spacing": "None"
        },
        {
            "type": "Container",
            "separator": true,
            "style": "attention",
            "items": [
                {
                    "type": "ColumnSet",
                    "columns": [
                        {
                            "type": "Column",
                            "width": "50px",
                            "items": [
                                {
                                    "type": "Image",
                                    "url": "https://normanhurb-h.schools.nsw.gov.au/content/dam/doe/sws/schools/n/normanhurb-h/icons/alert.png"
                                }
                            ]
                        },
                        {
                            "type": "Column",
                            "width": "stretch",
                            "items": [
                                {
                                    "type": "TextBlock",
                                    "text": "Action to take",
                                    "wrap": true,
                                    "separator": true,
                                    "color": "Accent",
                                    "size": "Small"
                                },
                                {
                                    "type": "TextBlock",
                                    "wrap": true,
                                    "spacing": "None",
                                    "text": "@{variables('ActionToTake')}"
                                }
                            ],
                            "verticalContentAlignment": "Center"
                        }
                    ]
                }
            ]
        },
        {
            "type": "ActionSet",
            "actions": [
                {
                    "type": "Action.OpenUrl",
                    "title": "See the original message",
                    "iconUrl": "https://normanhurb-h.schools.nsw.gov.au/content/dam/doe/sws/schools/n/normanhurb-h/icons/teams.png",
                    "url": "@{triggerBody()?['entity']?['teamsFlowRunContext']?['messagePayload']?['linkToMessage']}"
                },
                {
                    "type": "Action.OpenUrl",
                    "title": "Chat with @{outputs('Get_user_profile_(V2)_-_person_who_typed_the_message')?['body/displayName']}",
                    "iconUrl": "https://normanhurb-h.schools.nsw.gov.au/content/dam/doe/sws/schools/n/normanhurb-h/icons/teams.png",
                    "url": "https://teams.microsoft.com/l/chat/0/0?users=@{outputs('Get_user_profile_(V2)_-_person_who_typed_the_message')?['body/mail']}"
                }
            ]
        }
    ]
}

 


 




Thanks for reading! Hope you’ve learned loads yourself! 



Experiencing Data Access Issue in Azure portal for Log Analytics – 05/06 – Investigating

This article is contributed. See the original author and article here.

Initial Update: Thursday, 06 May 2021 08:16 UTC

We are aware of issues within Log Analytics and are actively investigating. Some customers may experience data access issues and delayed or missed Log Search Alerts in West Europe region.
  • Work Around: None
  • Next Update: Before 05/06 11:30 UTC
We are working hard to resolve this issue and apologize for any inconvenience.
-Mohsin Inamdar

EU Data Boundary for the Microsoft Cloud | Frequently Asked Questions

This article is contributed. See the original author and article here.

On May 6, 2021, we announced a new pledge for the European Union. If you are a commercial or public sector customer in the EU, we will go beyond our existing data residency commitments and enable you to process and store all your data in the EU. In other words, we will not need to move your data outside the EU. This commitment will apply across all of Microsoft’s main cloud services—Azure, Microsoft 365, and Dynamics 365. We are beginning work immediately on this added step, and we will complete by the end of next year the implementation of all engineering work needed to execute on it. We’re calling this plan the EU Data Boundary for the Microsoft Cloud. 


The new step we’re taking builds on our already strong portfolio of solutions and commitments that protect our customers’ data, and we hope today’s update is another step toward responding to customers who want even greater data residency commitments. We will continue to consult with customers and regulators about this plan in the coming months and move forward in a way that is responsive to their feedback. 


 


What exactly will change in 2022 from today? 


A: Many of our Online Services already offer customers data storage for Customer Data within customer-selected geographies, with many of Azure services offering the ability to choose to process and store Customer Data in customer-selected geographies. Through our new EU Data Boundary program announced on May 6th, by the end of 2022, we will be taking additional steps to minimize transfers of both Customer Data and Personal Data outside of the EU. We believe our new initiative will meet regulatory requirements and address the needs of our European customers who are looking for even greater data localization commitments. 


We’ve identified the technical and operational investments necessary to meet this goal, and we believe we can accomplish it. In the coming months we’ll be discussing our plans with both customers and regulators, and we will be responsive to their feedback.  
See: Microsoft Privacy – Where  your data is Located 


 


Will this result in a loss of functionality within the EU Data Boundary?  


A: The EU Data Boundary is a further development of our existing commercial services that we already offer within the EU and as such, will not require migration. Functionality and continued innovation will apply to the services within the new EU Data Boundary. Customers will still have the option to choose enhancements to services that leverage resources outside the EU boundary. 


 


Will the changes result in a price increase for EU customers? 


A: We will build these EU Data Boundary solutions into in-scope Online Services to enhance our current offerings for customers. There may be optional choices in the future, as is already the case with M365 MultiGeo. We will provide more information when it becomes available.


 


Do I need to wait until 2022 to migrate to the cloud?  


A: No. Customers considering migrating on-premises workloads to the Microsoft cloud today can be assured that they can use Microsoft services in compliance with European laws. Microsoft cloud services already comply with or exceed European guidelines even without the plan we are announcing today. These new steps build on our already strong portfolio of solutions and commitments that protect our customers’ data, and new customers will automatically gain the benefits of the engineering changes we are making. 


 


How will the new boundary impact my compliance with the GDPR and the Schrems II ruling?  


A: Microsoft Online Services already enable customers to comply with the GDPR even without this additional commitment to store and process data within the EU boundary. We implemented supplementary measures after the Schrems II decision to further support compliance for data transfers, which we believe meet and go beyond what is required by the Schrems II decision. We are making these additional investments to process and store data in the European Union by the end of 2022. This demonstrates our continuing commitment to our customers in Europe and simplifies post-Schrems II compliance by minimizing data transfers outside of the EU boundary.   
See: New steps to defend your data – Microsoft on the Issues 


 


Will EU Standard Contractual Clauses still be required or even applicable after 2022? 


A: The EU Standard Contractual Clauses (SCCs) are used in agreements between service providers (such as Microsoft) and their customers to ensure that any personal data leaving the European Economic Area (EEA) will be transferred in compliance with EU data protection laws and meet the requirements of the EU Data Protection Directive 95/46/EC.  


Microsoft will implement the European Commission’s revised SCCs and continue to offer customers specific guarantees around transfers of personal data for in-scope Microsoft services. This ensures that Microsoft customers can freely move data through the Microsoft cloud from the EEA to the rest of the world. Customers with specific questions about the applicability of SCCs to their own deployments should consult their legal counsel. 


 


How will the US and other government requests be treated under the new EU Data Boundary? 


A: Through clearly defined and well-established response policies and processes, strong contractual commitments, and if need be, the courts, Microsoft defends your data. We believe that all government requests for your data should be directed to you. We do not give any government direct or unfettered access to customer data. If Microsoft receives a demand for a customer’s data, we will direct the requesting party to seek the data directly from the customer. If compelled to disclose or give access to any customer’s data, Microsoft will promptly notify the customer and provide a copy of the demand unless legally prohibited from doing so. We will challenge every government request for an EU public sector or commercial customer’s personal data—from any government—where there is a lawful basis for doing so. And we will provide monetary compensation to our customers’ users if we disclose data in violation of the GDPR that causes harm.


 


Will any personal data be transferred outside the EU after 2022? Can you provide a list of exceptions? 


A: We’ve identified the technical and operational investments necessary to meet this goal, and we believe we can accomplish it. We will continue to consult with customers and regulators about our plans in the coming months, including adjustments that are needed in unique circumstances like cybersecurity, and we will move forward in a way that is responsive to their feedback. 


 


Will the EU Data Boundary be consistent with GAIA-X? 


A: While GAIA-X has not yet finalized its requirements, we believe the EU Data Boundary for the Microsoft Cloud will provide the technical and business basis to support our ongoing commitment to the GAIA-X initiative.

Azure Backup Center – Report on and Optimize your Backup environment.

Azure Backup Center – Report on and Optimize your Backup environment.

This article is contributed. See the original author and article here.

Hello folks,


In the first post in this series, we explored the overall capabilities


 


ABC is the one single place for all simplified backup needs.  As mentioned before, everything in one interface one place to discover and configure, to operate and to govern.  This is all well and good, however you still need to report your statuses so you can effectively:


 



  • Allocating and forecasting of cloud storage consumed.

  • Auditing of backups and restores.

  • Identifying key trends at various levels of granularity.


 


Therefore, in this final post we will review and dig into the optimization of those resources and capabilities. Like everything else in Azure, to analyze and report on resource usage, you need to link your operation to an Azure Monitor Logs workspace (formally Azure Log Analytics).  The location and subscription where this Log Analytics workspace can be created is independent of the location and subscription where your vaults exist.


 


 


In ABC we view the integrated Backup reports from the vaults.


 


abc report 1.png



You’ll first need to configure your vaults to use an Azure Monitor Logs workspace in the vault’s diagnostic settings.


 


abc report 2.png



When configuring the vault’s diagnostics settings, you need to specify the logs you want to collect.  You can pick from the list in the UI.  (Remember that the data you ingest in Logs Analytics Workspace does come at a cost in the workspace.)


You’ll also need to ensure that you select “Resource specific” in the destination table field to send vault diagnostics data to dedicated Log Analytics tables for backup.  Resource specific tables are individual tables in the selected workspace for each category selected in the diagnostic setting.  This is recommended because it makes it much easier to work with the data in log queries, it provides better discoverability of schemas and their structure, improves performance across both ingestion latency and query times, and the ability to grant Azure RBAC rights on a specific table.


 


abc report 3.png



The reports will give you all the info you need regarding:



  • Backup Instances

  • Usage

  • Jobs

  • Policies

  • Optimize

  • Policy Adherence


Having access to all this telemetry enables you to make decisions regarding strategy, allocation and forecasting of cloud storage consumed by your backups.


 


The point here, is that Azure Backup Center centralizes the access to those reports to your tasks of managing your protection strategy.


 



  • Learn more and get started with Backup center.

  • Tell us how we can improve Azure Backup by contributing new ideas and voting up existing ones in the Azure Backup feedback forum.


I really hope this series was valuable for you and that Azure Backup Center is on your list of services to investigate.


 


Cheers!

Surface Pro X can now take advantage of Universal Print

Surface Pro X can now take advantage of Universal Print

This article is contributed. See the original author and article here.

Universal Print now supports Windows 10 on ARM devices, such as Surface Pro X.  As a modern, cloud-based print solution, Universal Print removes the need for on-premises print servers and enables endpoints to print to Azure AD-registered printers. Universal Print is the perfect match for cloud-first devices like Surface Pro X and helps enterprises unblock their move to the cloud.


 


With Universal Print, workers benefit from driverless printing, streamlined location-based printer discovery, and an intuitive printing experience. With Azure AD integration, workers use existing AAD credentials to print from workplace-joined devices.


 


Universal Print allows IT departments to configure their organization’s printers so that employees can print seamlessly from any device, and for organizations to lower the cost of printing, while supporting their business needs. Administrators can manage print infrastructure from the Universal Print admin portal and connect printers with native support for Universal Print.


 


The Universal Print API expands the capability and reach with an existing robust ecosystem of partner solutions. 


 


To learn more about getting started, check out the Universal Print FAQ


 


universalprint.png


 

How to manually add devices in Apple Business Manager (ABM) or Apple School Manager (ASM)

How to manually add devices in Apple Business Manager (ABM) or Apple School Manager (ASM)

This article is contributed. See the original author and article here.

By Marc Nahum Sr Program Manager | Microsoft Endpoint Manager – Intune


 


Any enterprise or education institution that owns iOS/iPadOS devices can take advantage of automatic enrollment to Intune, as well as the extra features and controls that Apple’s Automated Device Enrollment (ADE) – previously known as Device Enrollment Program (DEP) – provides.


 


When ADE was first introduced, only Apple resellers or telecom carriers were able to add devices to Apple Business Manager or Apple School Manager. However, since the release of iOS 11, Apple supports the ability to manually add iOS and iPadOS devices yourself with the Apple Configurator 2.5 (AC2) tool. This means that, regardless of where the device was purchased, you can benefit from using ABM or ASM.


 


This article will help IT pros and mobile device administrators understand the steps required to manually add iOS and iPadOS devices to Apple Business Manager or Apple School Manager, as well as enrolling them into the Intune service.


 


Note: Manually adding devices (new or old) is not supported for macOS. For these devices, the reseller must carry this out for you, no matter when they have been purchased.


 


Warning: The devices will be fully wiped during the process. This happens because Apple treats a device being in ABM as proof of ownership.


 


Before proceeding, there are some configurations, constraints, and restrictions to understand, after which the process is straightforward.


 


Prerequisites:



  • A Mac device (desktop or laptop), running at least macOS Catalina (macOS 10.15.6 or later). This is mandatory as AC2 only runs on macOS.

  • AC2 installed on the Mac from the App Store (Apple ID required). A version can be downloaded from the Apple developer site, but it requires an Apple developer membership account. This can be useful if you want to distribute the pkg with Intune on the Mac who will have to use it.

  • Physical access to the iOS/iPadOS device, which must be connected to the Mac device running AC2. It must not have Apple’s “Find My” turned on (Activation Lock off).

  • An ABM or ASM account with the role of “Device Enrollment Manager” assigned.

  • A network profile in AC2 (steps detailed below) to allow the iOS or iPadOS device to connect to the Internet during the process.

  • ABM or ASM configured with Microsoft Endpoint Manager as an MDM Server (Settings > Device Management Settings > Add MDM Server).


 


Preparing Apple Configurator:


There are a lot of options in AC2, so we will cover only the steps necessary to import the devices to ABM or ASM and assign them to the Microsoft Endpoint Manager MDM server. You can find full documentation from Apple here.


 


1. Creating a Wi-Fi profile


 


During the onboarding process, the device will need to connect to the internet. Therefore, it’s mandatory to have a Wi-Fi profile, which will allow it to automatically connect. The profile can be as complex as is required, but must not prompt the user for any action, or require a certificate to authenticate.


 



  1. In Apple Configurator go to the File menu and choose New Profile.

  2. Complete the Name of the profile in the mandatory General section.

  3. Complete the Wi-Fi section with your parameters.

  4. Once created, save it by clicking on the name on the top of the window. You can then close it and it will be used later.


 


Screenshot of a Wi-Fi profile and configured settings in Apple Configurator 2Screenshot of a Wi-Fi profile and configured settings in Apple Configurator 2


 


2. Generate MDM Server URL for Microsoft Endpoint Manager


 


Note: This step is not mandatory, but it will create a trusted configuration and avoid any doubts that the URL is the proper one.


 



  1. Open Microsoft Endpoint Manager admin center.

  2. Select Devices, then navigate to Enroll devices > Apple enrollment > Apple Configurator.

  3. Select Profiles > Create.

  4. Complete all required fields with your desired configuration, then click Create.

  5. Select the profile you just created, then click Overview > Export Profile.

  6. Copy the Profile URL from the Setup Assistant Enrollment section on the right-hand side. This will be used later.



Screenshot of the Apple Configurator - Default Enrollment Profile in the Microsoft Endpoint Manager admin centerScreenshot of the Apple Configurator – Default Enrollment Profile in the Microsoft Endpoint Manager admin center


 


Connect the device to Apple Configurator


 


Important: The device will be fully wiped during this process.


If this is the first time you are connecting the device to the Mac, a pop up will appear asking for the Mac to be trusted, select Trust. Now the device is ready to be prepared.


 



  1. In Apple Configurator, select Prepare from the toolbar or by doing a secondary click on the picture of the device.

    Screenshot of Apple Configurator 2 with an arrow pointing to the "Prepare" optionScreenshot of Apple Configurator 2 with an arrow pointing to the “Prepare” option


  2. The below settings must be selected:

    • Manual Configuration.

    • Add to Apple School Manager or Apple Business Manager.

    • Allow devices to pair with other computers.


     


    Do not select:



    • Activate and complete enrollment.

    • Enable Shared iPad.

      Apple Configurator 2 - Prepare Devices" menuApple Configurator 2 – Prepare Devices” menu




  3. If this is the first time the operation is run on this Mac, you will have to create a “New Server” with the following details:


    Name: “Microsoft Endpoint Management”


    URL: The one created in the step “Generate MDM Server URL for MEM


    Example URL: https://appleconfigurator2.manage.microsoft.com/MDMServiceConfig?id=<Intune_tenant_ID>&AADTenantId=<AAD_tenant_ID>


    Apple Configurator 2 - "Define an MDM Server" menuApple Configurator 2 – “Define an MDM Server” menu

    Note: If you decided to skip the step of creating the dedicated URL from the Intune portal, you can simply use “https://endpoint.microsoft.com” and acknowledge the warning “Unable to verify the enrollment URL” as per below:

    Apple Configurator 2 - "Define an MDM Server" menu with the warning text: “Unable to verify the enrollment URL”Apple Configurator 2 – “Define an MDM Server” menu with the warning text: “Unable to verify the enrollment URL”


  4. Add trust anchor certificate for MDM server.

    • Select the one with the Microsoft or Azure name on the list (this should be appleconfigurator2.manage.microsoft.com or portal.azure.com or endpoint.microsoft.com)




  5. Attach the device to your organization.

    • Next, authenticate to ABM/ASM with an account with the “Device Enrollment Manager” role assigned.

      Apple Configurator 2 - Sign in to Apple School Manager or Apple Business Manager menuApple Configurator 2 – Sign in to Apple School Manager or Apple Business Manager menu



    • If you did not set up the organization name, you will need to do that next. That Organization name will be displayed on the device.




    • The iOS setup assistant steps selected on the next screen are not important as they will be defined in Intune later.




    • Next, select the Network Profile previously created and, when prompted, enter your local password to initiate the process.




    • At this point, the device will be erased. When the device has restarted, steps in AC2 are complete.






 


Log on your Apple management console


You now need to assign it to Intune in the ABM/ASM console. By default, it’s assigned to an MDM server configuration named “Apple Configurator 2”:


 













Screenshot of an Apple iPhone 6 device in the ABM/ASM consoleScreenshot of an Apple iPhone 6 device in the ABM/ASM console Screenshot of the ABM/ASM console with associated Apple devicesScreenshot of the ABM/ASM console with associated Apple devices
You can reassign 1 device by selecting that device and choosing:
Edit Device Management > Assign to server and select the proper Intune one.
You can reassign multiple devices by doing the same with filters and choose “Edit Device Management” > “Apple Configurator 2”

 


Microsoft Endpoint Manager admin center


Once the device is assigned it will need to be synchronized. This occurs automatically every 12 hours or you can manually trigger the synchronization in Microsoft Endpoint Manager admin center:



  1. Navigate to Devices > Enroll devices > Apple Enrollment> Enrollment program tokens and select your token name.

  2. Navigate to Devices and click Sync.


 


Note: You can manually synchronize the devices from ABM/ASM to Intune at a maximum frequency of every 15 minutes.


 


At this point you should have successfully added your ADE device to Intune.


 


Let us know if you have any questions by replying to this post or reaching out to @IntuneSuppTeam on Twitter.

[Guest Blog] Stretch Goals will change your life

[Guest Blog] Stretch Goals will change your life

This article is contributed. See the original author and article here.

This blog is written by Jerry Weinstock, Microsoft Business Applications MVP. He shares how he set and pursued stretch goals to become a Business Applications MVP and author a white paper for Microsoft.


Jerry on bike.png


When you hear the term “Stretch Goals” it is usually in the context of performance metrics for sales people on quota or commission. I am going to tell you two stories where I have used stretch goals to take my career to the so-called next level by getting me out of my comfort zone and accomplishing bucket list items. Stretch goals are also for technology people!


 


When we think about goals they are generally conservative, somewhat routine and tend to be achievable and perhaps expected to be accomplished. Do not confuse it with “doing your job” and getting a positive review along with the standard merit increase. New Year’s Resolutions are not stretch goals!


 


A stretch goal is an objective that you set for yourself that is extremely difficult to achieve. It is over and above your normal activities or the results that others expect you to achieve. While there are many ways to define a stretch goal, in my life I have defined it by two criteria; it will take me well out of my comfort zone, requiring me to “stretch” well past my current level of activities and skill level; and it will be something when achieved, is “braggable” either in a personal or business setting. It could also be a bucket list accomplishment but not everything that might fall into a bucket list checklist is a stretch goal.


 


So now that we have a baseline for stretch goals, let me tell you about two stretch goals that took me well out of my comfort zone, provided some things I could brag about, and catapulted my career to another level.


 


Microsoft CRM Team Blog – My path to becoming a MVP


Back in the early days – circa 2007-2009, the Microsoft CRM Team Blog (that was its’ name then) was just about the only place online that you could find new product information being posted. We did not have Facebook or Twitter the way it’s used today, nor Linkedin. Additionally, very few people were blogging on their own website. It was the one place you went to almost every day to get the latest CRM news.


 


I had been voraciously consuming the blog posts as soon as they came out, applying the new found knowledge to projects for my clients. I had noticed a pattern that some of the posts were being made by non-Microsoft people and labeled as “guest posts”. After a while of seeing these posts, I began to think that I had equally good information to share as these guest bloggers. I just had never done anything like that before and I had no clue how to break into the process. All I knew was that all the guest bloggers were MVPs. While I had no direct exposure to these people I knew from seeing them at events and their entourage that they seemed a step ahead of all the other consultants.


 


So while I had given no thought to becoming an MVP, I also had no clue where to begin the process. I got it in my head that if I tried, I could write equally valuable blog content. I started working on several candidate posts that went through dozens of iterations. Finally, when I had something that I thought might work, I tracked down Jim Glaas who, at the time, ran the MVP program and managed the team blog. After pinging him with emails, I finally connected with him and we started the process. The first post I submitted was turned down because it was based on what the product team assessed as unsupported methods. I was devastated and almost retreated. The second submission I came up with was accepted and on September 9, 2009 the first post appeared – A Plethora of Phone Attributes.


 


plethora.jpg


 


After successfully getting one post accepted and basking in the glory for a few minutes (my family wasn’t impressed), I set out to see if I could continue to stretch and repeat the accomplishment. I had several more published, one of them is as follows:


 


marketing.jpg


 


Concurrent with the posting of the Marketing list post, I received an email from Jim asking why I wasn’t a CRM MVP. He advised that if I spent a lot of time in the CRM forum, it would greatly boost my chances. I took him up on it without knowing much about the MVP program, but I felt confident that if I pushed myself, I could demonstrate I was equally qualified.


 


I received the MVP Application form in January 2010. I then set out to diligently become more active on the community forums. Every morning, as soon as I got to the office, I went to the forums and tried to answer the questions that had been posted the night before. In many cases I actually had to create the submitters’ scenario in CRM to come up with the answer. This went on for months, sometimes my real work didn’t get started for 2+ hours after the day began.


 


I applied to the MVP program with the formal application in April and was notified that I had been turned down and to re-apply. I decided to ramp it up even more and delivered another guest post and stretched myself to answer even more complex questions on the forums.


 


error.jpg


 


On October 1, 2010 I received the email letting me know that I had been recognized for my community activities and entered the MVP program. It is coming up on 11 years now and I consider it the single biggest professional stretch goal I have accomplished. It has had more impact on my business and personal life than any other career event. Put your mind to it and stretch yourself, you can do it also if you want it.


 


Microsoft White Paper – Power Automate Flow


Just like I had been observing the guest posts by MVPs circa 2008, I had been consuming Microsoft White Papers. I always marveled over the value of the content along with the prestige that seemed to come to people that were skilled enough to put them together. I had jumped on Microsoft Flow when it was first introduced and felt it was the most powerful tool that the product team had given to functional consultants in the life of the product. After blogging, speaking, and answering forum questions for the first two years I believed I had defined myself as the go to person in the community for Flow and Dynamics 365.


 


I decided to set my next stretch goal – to firmly establish myself at the pinnacle of Flow and Dynamics 365. After a long and brand new process that took me through selling the idea to Microsoft and then actually delivering on what I told them I could do, in August of 2009 the Flow white paper was released. Did I stretch myself? You bet, the paper went through four iterations with Microsoft and I invested three times the amount of hours that I had originally estimated but I was ecstatic when it was released. It certainly falls into the braggable category. Would I do it again? I could but probably wouldn’t and perhaps that is the third criteria of a stretch goal – something you achieve but only need to do once.


 


flow.jpg


 


So that kind of sums it up – get out of the routine, think big, take yourself to the next level, accomplish something that no one around you has, look to the leaders that you know, set a stretch goal for yourself and when you achieve it – tell the world. You will have a smiling grin on your face.