-
Notifications
You must be signed in to change notification settings - Fork 516
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement support for Privacy Manifests #20059
Comments
Are there any updates of this issue, or is there any action in another repository to address this issue? Apple writes:
If things go as planned by Apple, .NET apps on iOS might be at risk of being rejected for publication or updates by the store this spring. (though Unity seems to be dealing with it in their own way) We are seeking some workaround which can be done only by ourselves, without framework support, but it might be impossible. |
Here is an example of a Framework that contains the file <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>35F9.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>C617.1</string>
<string>3B52.1</string>
<string>0A2A.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>E174.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
</array>
<key>NSPrivacyTracking</key>
<false/>
</dict>
</plist> |
If we wanted to implement this well, here's an idea: We add a new attribute: [AttributeUsage (AttributeTargets.Assembly | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Constructor | AttributeTargets.Class, AllowMultiple = true)]
public class PrivacyManifestRequirementAttribute : System.Attribute {
// The value for the NSPrivacyAccessedAPIType key in the privacy manifest
// For instance "NSPrivacyAccessedAPICategoryFileTimestamp" for file stamp APIs.
public string AccessedApiType { get; set; }
// A description?
public string? Message { get; set; }
// A url to a longer description?
public string? Url { get; set; }
public PrivacyManifestRequirementAttribute (string accessedApiType)
{
AccessedApiType = accessedApiType;
}
} Then we decorate every API that triggers the privacy manifest requirement with this attribute. Note that there are APIs in System.Private.CoreLib.dll that triggers the privacy manifest requirement, so this attribute would probably have to be added to System.Private.CoreLib.dll. If we use such an API internally (either in the runtime or our own code, and the developer can't not use it in any way), we can add the attribute to the assembly in question (either System.Private.CoreLib.dll or Microsoft.iOS.dll). And finally we handle this attribute in a way similar to how the linker handles trimmability attributes such as the RequiresUnreferencedCodeAttribute: any method that calls another method with this attribute must also have the equivalent attribute, otherwise a warning is raised. For executable projects, the warning can be silenced by adding a privacy manifest to the project with the correct privacy information. The downside is that this is a significant amount of work upfront, but it pays off once done: there's no manual validation needed once the initial set of APIs have been annotated, the compiler/code analyzers will yell if the attribute isn't forwarded where it needs to be. If Apple adds more APIs to their list of special APIs, the process is very straight forward on our side: we annotate the corresponding APIs, and then, once again, we'll get warnings everywhere we need to forward the attribute. If we decided to look into this, we should talk with the linker team for any input from them. |
This sounds like a good and extensible approach and I think we should definitely aim our implementation in that direction. However, as you rightfully pointed out, I also feel it would take a lot of time/work before we get there. Especially if we consider, acceptance on the Since Apple announced that the privacy manifests will be checked starting on Therefore, I think as one of the first things to agree upon (which we can utilize in the future) is to define a format which Xamarin bundler would use when producing the For example, one idea for the short-term solution would be that we (on The static list of privacy accessed APIs and the MSBuild target could be something like this: <Target Name="CollectPrivacyRequirements" Condition="'$(_IsPublishing)' == 'true'" AfterTargets="<TBD>">
<ItemGroup>
<NSPrivacyAccessedAPITypes Include="NSPrivacyAccessedAPICategoryFileTimestamp">
<NSPrivacyAccessedAPITypeReasons>0A2A.1</NSPrivacyAccessedAPITypeReasons>
<NSPrivacyAccessedAPIDescription>Used by C# timestamp APIs</NSPrivacyAccessedAPIDescription>
</NSPrivacyAccessedAPITypes>
<NSPrivacyAccessedAPITypes Include="NSPrivacyAccessedAPICategoryFileTimestamp">
<NSPrivacyAccessedAPITypeReasons>C617.1</NSPrivacyAccessedAPITypeReasons>
<NSPrivacyAccessedAPIDescription>Used to check files</NSPrivacyAccessedAPIDescription>
</NSPrivacyAccessedAPITypes>
...
</ItemGroup>
</Target> NOTE: As an example I used some information Unity includes in their documentation. This way our users (and other frameworks MAUI?) could also plug-in and extend the Finally, as a follow-up we would replace this manual process with something more sophisticated and automatic that is compatible with our toolchains similar to what you proposed, but with the same "back-end" that produces the |
I absolutely agree with Ivan that it seems we need a short-term solution which is reasonably easy to implement. |
Actually, the analyzer change has already been merged: dotnet/runtime#94944 |
What happens if the linker removes all of the usages of said APIs and there is no need for a privacy manifest? Could we make this more opt-in? For example document all the runtime/macios/MAUI usages and then let the final user fill in the above proposed item groups on their own so we can generate the main bundled privacy manifest. Then once we have the more advanced annotations we can have the analyzer or linker step to produce this automatically in the future.
I agree, we need a short term solution now if the long term one is not ready to be implemented on the runtime side. |
I think without some more involved changes (attributes, tooling support, ...) it will be hard to detect the need for this reliably. So I would probably go with the "Unity" approach - add the stuff which runtime may need always. If developers don't want it for some reason, it's a single line of MSBuild to remove everything we put there by default anyway. In fact for the first version of this, we might go with just some docs, where we provide the snippets for the runtime and the frameworks and so on, ant let it up to the developer to construct the final XML. For the long term solution - just a question:
|
It's the developers who have to create the privacy manifest. Only they know why they're using a particular API, and they have to explain the reason in the privacy manifest. All we can do is say "hey, if you use this managed API, then you're effectively using this other native API, which means you'll then you'll have to explain why in the privacy manifest". At most we can create a privacy manifest with a placeholder reason - but the developers still have to review why they're using the APIs in question.
We might want to wait until Xcode 16 in June to see what else (if anything) Apple comes up with until we start looking at the long term solution, just in case they throw the whole thing out and do something completely different. |
Thanks a lot @rolfbjarne for explaining this to me. |
Couldn't that be accomplished by only adding the attribute in the implementation assembly for iOS? That way other platforms wouldn't even see the attribute. |
I got tagged on this for the IDE-side of things. From what I can tell, the IDE won't really need anything because this is all just a plist. Correct? Maybe, at most, we could maybe add a schema file for the plist editor that we already have? |
That would work for trimmer/NativeAOT, but not for the analyzer. The analyzer (since it's in Roslyn) sees reference assemblies, and if I understand it correctly, we have only one set of reference assemblies, they are not RID specific. |
Is not that just a plist file inside bundled release IPA ? That way, you could add a custom msbuild step that copies that from project into IPA after build/package step as a temporary workaround + short tutorial/guide how to create it via XCode. You could think and polish better solution for net8/net9+ then - more time to do so for you. That could give a support for old xamarin workflows (just copy-paste build-step into csproj) as well (XCode 15 support been added to give more time for migration which is a total pain even for non-forms apps) |
Please keep in mind, that a solution for this might be needed for .net 7 as well. We have an app publishes using ,net 7 and did not upgrade to .net 8 until now because of known bugs in .net maui 8. Thanks! Apple will check this starting 1st May 2024. |
First warnings ( ITMS-91053 , for referencing) have started rolling in (see dotnet/maui#21296). Thank you @rolfbjarne for pointing me toward this issue! I have read the PR #20292 and you guys are really making a great job with platform-specific documentation (kudos @mcumming ). You are very often filling the holes in Google's/Apple's docs. Thank you for that! In the PR, I found the answers both regarding since when the warnings started to be sent (March 13th) and which warnings are caused by MAUI/Xamarin-macios (I myself am not directly using any of the APIs from the warnings). Quoting Rolf
Not so easy really, I am glad I haven't pulled too many 3rd parties to my app... |
@FM1973 correct, this is needed for any app that you want to release or update in the Apple App Store after May 1, 2024, regardless of what technology or what version of a technology it is built with. Luckily no new functionality has to be implemented for this. As long as you can figure out what the The mechanisms to add a file in your app bundle is already working and implemented for a long time, so that should not be the issue. |
what do us legacy Xamarin users do to our projects do we have to manually create this privacy file for example my email contained this
|
@LennoxP90 yes, the same applies to legacy Xamarin (or any iOS app), add that file with the right contents to the root of your app bundle and you're good to go. You do want to understand why these entries are there obviously so you can explain that to your users, but in this case this seems to be the exact APIs that are used by the .NET runtime and Xamarin(.Forms/.Essentials) so that checks out. |
Do we have a template for people to use if the only APIs you use are the ones used by the .net runtime? |
@Gekidoku I just opened a PR to add the minimal needed version to the .NET MAUI templates, find that here: dotnet/maui#21350 If you're using .NET for iOS without MAUI you can leave out the |
From https://developer.apple.com/news/?id=3d8a9yyh > Starting March 13: If you upload a new or updated app to App Store Connect that uses an API requiring approved reasons, we'll will send you an email letting you know if you’re missing reasons in your app’s privacy manifest. This is in addition to the existing notification in App Store Connect. > > Starting May 1: You’ll need to include approved reasons for the listed APIs used by your app’s code to upload a new or updated app to App Store Connect. If you’re not using an API for an allowed reason, please find an alternative. And if you add a new third-party SDK that’s on the list of commonly used third-party SDKs, these API, privacy manifest, and signature requirements will apply to that SDK. Make sure to use a version of the SDK that includes its privacy manifest and note that signatures are also required when the SDK is added as a binary dependency. [Document preview](https://github.com/xamarin/xamarin-macios/blob/928100b38fa3400a01cc9c862426c49a9937cfdc/docs/apple-privacy-manifest.md) fixes: #20059 --------- Co-authored-by: Rolf Bjarne Kvinge <rolf@xamarin.com> Co-authored-by: Haritha Mohan <harithamohan@microsoft.com> Co-authored-by: Alexander Köplinger <alex.koeplinger@outlook.com>
@mcumming I believe there is a typo here (it should be
I also pointed it out in the PR, but maybe it was overlooked. |
@jfversluis would it make sense to have a FileTemplate for the |
Here (search for NSPrivacyAccessedAPICategoryUserDefaults) i see them list it as CA92.1 so is this apple making a typo in their documentation read versluis's comment below. ty for the quick work jversluis |
@tipa @Gekidoku that typo should be fixed by #20352 is there still something wrong? @jstedfast oh like a FileTemplate in Visual Studio that people could add? Great idea, but my knowledge of the templating engine is limited. I think I wouldn't be able to add an entry to the csproj? If I can't do that with the template I'd say its value is limited. People will still have to go out and find out how to make the privacy manifest file show up in the right place. If they're going to do that, the extra step to paste in the contents isn't that big? Maybe I'm not understanding you correctly or hopefully this is possible with templates. Feel free to reach out offline and discuss a bit more! |
The dotnet engine already has FileTemplates that get added to the .csproj when a user selects them in the "Add New Item" dialog box, so it's definitely possible. |
Hi, |
@AlleSchonWeg whenever you have the file with the correct contents it should work with whatever Apple decides. As mentioned in the linked forum post as well, here it mentions:
That is also all the information we have at this moment, and if I were to believe this, it should just work whenever you add the correct privacy manifest to your host app, in this case your .NET for iOS or .NET MAUI app. |
We should look into what we need to do with regards to Privacy Manifests: https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_use_of_required_reason_api
The text was updated successfully, but these errors were encountered: